2015/12/24

Qt5에서 ActiveX 사용


Qt5를 갖고 놀고 있는데 ActiveX를 사용해야 할 일이 생겼다. ActiveX를 걷어내야 한다고 아우성치는 마당에 내가 생각해도 좀 웃프다. Windows 프로그램을 짜본 적이 없어서 ActiveX니 COM Object니 하는 것들이 낯설다. 그래도 몇일 뒤면 잊어 버리기 때문에 정리해 두고 간다.

Qt가 좋은 점이 Multi-platform을 지원하기 때문에 특정 OS API를 몰라도 쉽게 사용할 수 있다는 점이다. 요즘은 Python을 많이 사용하는 추세인듯 싶은데, PyQt 같은 것을 써도 아래의 기본적인 방법들을 똑같이 적용할 수 있다.

기본적으로 Qt Document 홈페이지에서 ActiveQt 사용법에 대한 기본적인 정보를 얻을 수 있다. 하지만, 실제로 프로그램이 돌아가도록 하려면 기본적인 정보만으로는 부족하더라.

Qt 프로젝트 설정

우선, ActiveX Control을 사용하기 위한 Class는 QAxWidget이다. 이 놈의 애비는 QAxBase이고, COM Object를 지원하는 QAxObject는 형이다. 이 놈들을 사용하려면 Qt 프로젝트 생성 후에 Qt 프로젝트 설정 파일(*.pro)에 아래와 같이 설정을 추가해야 한다.
QT += axcontainer

Qt 프로그램에 ActiveX Control 불러오기

ActiveX Control은 3rd Party가 제공하는 것이다. 우리나라에서는 Internet Explorer로 웬만한 웹사이트 돌아 다니다 보면 설치해야 하는 경우가 허다하다. 아무튼 이놈들이 설치되면 Windows Registry에 Class로 등록이 되고, 각자 고유한 Class ID(CLSID)를 갖고 있다. ActiveX Control을 사용하려면 이 CLSID 또는 고유한 이 Object의 명칭을 알아야 하고 아래와 같이 불러올 수 있다.

QAxWidget *axControl = new QAxWidget("{CLSID}"); 또는,
QAxWidget *axControl = new QAxWidget("고유 명칭");
위에서 CLSID는 실제 등록된 값을 사용해야 한다. 예를 들어, AAAAAAAA-1111-BBBB-1111-AAAAAAAAAAAA와 같은 값이다. 또는 아래와 같이 해도 된다.

QAxWidget *axControl = new QAxWidget;
axControl->setControl("{AAAAAAAA-1111-BBBB-1111-AAAAAAAAAAAA}");
초기화가 됐으니, ActiveX Control이 제공하는 함수나 Event들을 Qt 애플리케이션에서 사용할 수 있게 된다. 프로그램에서 사용하려면 매뉴얼이 있어야 하겠지만, API Header를 dump 받을 수도 있다.

ActiveX Control의 함수 사용

가령, ActiveX가 제공하는 아래의 함수를 사용하려면 QAxBase가 제공하는 dynamicCall()을 사용하면 된다. 물론, Windows의 변수 Type에 대응하는 Qt 변수 Type을 사용해야 한다.
CString GetData(LPCTSTR sRQ, LPCTSTR sCode, long index);

QString sRQ="RQ", sCode="1111";
int index = 0;
QVariant received = axControl->dynamicCall("GetData(QString, QString, int)", sRQ, sCode, index);
QString result = received.toString().trimmed();
ActiveX나 COM Object에서 Variant Type을 사용할 경우 QVariant Type을 사용하면 된다. QT가 제공하는 dumpcpp를 사용할 수 있다면 dynamicCall 보다 C++ 스럽게 ActiveX Control 함수를 사용할 수도 있다.

ActiveX Control의 Event 사용

3rd Party ActiveX Control을 사용할 때 매뉴얼이 부실한 경우도 많고, API를 dump할 경우에도 함수 Prototype은 알 수 있지만, Event 함수의 Prototype을 알 수 없을 경우도 있다. 특히, ActiveX Control이 네트워크 상의 서버에서 데이터를 가져오는 기능을 할 때 애플리케이션에서 요청한 데이터가 준비됐는지를 알려면 ActiveX Control이 제공하는 Event를 반드시 사용해야 한다. 다행히, Qt Designer를 사용하면 ActiveX Control이 제공하는 Event Prototype을 알 수 있다.

예를 들어, ActivX Control이 제공하는 Event Prototype이 OnReceive(QString, int, QString)이라면, 아래와 같이 Qt의 Signals & Slots를 사용하면 된다.
connect(axControl, SIGNAL(OnReceive(QString, int, QString)), this, SLOT(onReceive(QString, int, QString));

MyClass::onReceive(QString RQ, int index, QString sCode)
{
    qDebug() << RQ << index << sCode;
}
즉, MyClass::onReceive()에서 ActiveX Control이 넘겨준 값들을 사용할 수 있게 된다.

2015/11/21

Windows 10 Build 10586 Upgrade


어제 Windows 10 버전 1511 (Build 10586.11) 업그레이드가 떴길래 업그레이드 했다. Windows 10 출시 당시 버전은 Build 10240이었다. 첫번째 Windows 10 major update인 셈이고 예전 Windows로 치면 Service Pack1에 해당하는 업그레이드인 셈이다.  업그레이드 과정을 보니 Windows 10을 새로 설치하는 것과 똑같다. 참고로, 이번 Upgrade시 대략 1시간 반 정도 걸린 듯하다. 예전에 Windows 10 Clean Install에 대해 글을 올리면서 엄청난 노가다 불평을 늘어 놨었는데, 새로운 버전은 노가다를 많이 줄일 수 있을 듯하다.

그 이유는 Microsoft가 이번 Windows 10 Upgrade 버전부터 Windows 7이나 Windows 8 License Key를 Windows 10 설치 후 Activate할 수 있도록 풀어 놓았기 때문이다. 즉, 이전 버전 Windows 사용자 들도 곧바로 Windows 10 Clean Install을 할 수 있게 됐다는 것이다.

이로 인해 Windows 10 사용자가 많이 늘어 날 수 밖에 없을 것이다. Microsoft가 초기에 DOS를 공짜로 풀어 놓던 시절과 비슷한 정책을 사용하려는 것 같다. Windows 10을 공짜로 풀고 사용자가 늘어나면 1 Device당 Windows 1개라는 정책이 상당한 효과를 보게 될 것이기 때문이다.

아무튼, 여기를 보면 실제로 몇가지 달라진 점이 있지만, 구 버전 Product Key를 사용할 수 있게 함으로써 Clean Install이 매우 쉬워 졌다는 점이 어쩌면 이번 Upgrade의 중요한 Point가 아닌가 한다. Windows 10 설치 iso 파일은 여기서 내려 받을 수 있다.

Windows 10의 몇가지 문제들: Display, 부팅 시간, 일부 설정 기능 먹통 증상 

Windows 10을 설치한 PC가 2대인데 하나는 내장 Intel Graphics Card와 NVIDIA Graphics Card가 탑재된 초기 Optimus 방식을 사용하는 Dell Alienware 노트북이고, 하나는 NVIDIA가 탑재된 iMac이다.

Alienware의 경우엔 두 개의 Display Adaptor Driver가 모두 설치되는데 Windows 10에서 화면이 아예 Black Screen으로 나타나거나 해상도가 낮아지는 문제가 발생할 수 있다. 이 경우엔 제어판의 [장치관리자] > [디스플레이 어댑터]에서 둘 중 하나를 "사용 안함"으로 설정 후 재부팅하면 문제가 해결된다.

iMac의 경우엔 NVIDIA 드라이버만 설치했는데 문제는 부팅속도가 1~2분 정도로 매우 느려지는 문제가 생긴다. Windows 10 처음 Clean Install 했던 때부터 발생한 문제였는데 우분투를 주로 쓰다보니 큰 문제라고 생각하지 않았었다. 구글링해 보니 Windows 10 사용자들 중에 부팅속도가 느리다는 불만이 의외로 많더라. 해결방법도 가상메모리를 고정시키거나 Fast Startup 옵션을 해제하는 법 등 여러가지가 있었는데 모든 방법을 다 해보아도 Alienware의 Widows 10 부팅속도와 비교하면 엄청나게 느리다. 혹시나해서 [장치관리자]에서 NVIDIA 디스플레이 어댑터를 "사용 안함"으로 설정하니 부팅속도가 20초 정도로 줄어 들었다. 3D 가속을 사용하지 않을 경우엔 이 방법을 당분간 사용하기로 했다.

Windows 10 부팅 속도 문제는 Windows 10 출시 전부터 발생한 문제인듯 하고, 현재 Upgrade에서도 해결되지 않은 듯하다. 일부 PC에서만 발생하기 때문에 일반적인 문제는 아니다. 구글링해 보면 Clean Install 하면 해결될 수 있을 것이라는 글도 있지만, iMac의 경우엔 Clean Install 했는데도 문제가 생기는 걸 보면 Windows 10의 미해결 문제인듯 하다.

iMac의 경우에 Boot Camp 드라이버를 설치하면 Windows 10에서 모든 장치가 제대로 동작하는데, OS X 디스크 파티션도 Windows에서 사용할 수 있게 보여준다. 문제는 Windows 10의 [시작 메뉴] > [설정] > [시스템] > [저장 공간] 이나 일부 다른 기능을 선택하면 프로세스가 먹통이 된다. 이 역시 Windows가 HFS 파일 시스템을 인식하지 못하기 때문일 거라는 생각에 [디스크 관리]에서 드라이버 문자를 삭제했더니 문제가 해결됐다.

Windows 10 Upgrade 도중 grub rescue> 모드 진입

Windows 10 OS 파티션을 넉넉하게 잡아 놓은 탓에 Upgrade 도중 재 부팅시 grub rescue> 모드로 진입하는 일이 벌어졌다. 알고 보니 OS X El Capitan 업그레이드 시와 동일하게 Windows 복구 파티션을 자동으로 Windows OS 파티션 끝을 쪼개서 추가해 버렸기 때문에 발생한 문제였다.

이번에 Grub을 복구하면서 예전의 "Ubuntu BIOS 및 UEFI Grub 복구" 게시물을 보완하였다. grub recue> 모드에서의 Grub 복구 방법을 참고하면 된다.

Grub을 복구한 후 다시 Windows를 선택해서 부팅하면 정상적으로 Upgrade를 완료할 수 있게 된다.

맺음말

Windows 10을 사용하고자 하는 이들에게 이번 Upgrade가 상당히 매력적인건 사실이다. 하지만, 나도 모르게 Windows 정책에 종속되게 된다는 점 또한 잊지 말아야 할 것이다. 구 버전의 Windows 들을 버리지 말고 유산으로 잘 간직해 두길...

2015/10/28

Ubuntu 15.10 Upgrade


지난 주에 우분투 15.10이 나왔는데 주말에 15.04였던 놈을 Software Updater를 사용해서 15.10으로 Upgrade했다. 대개는 Clean Install을 했었는데 우분투 홈페이지에서 15.10의 새로워진 점을 보았더니 크게 사용자가 느낄 정도로 달라진 점은 없어 보였기 때문이다. 대략 1시간 반 정도 걸렸다. 우분투 15.10에 대한 새로운 기능들은 여기를 참고하면 더 도움이 된다.

대체로 이번 Upgrade는 15.04의 버그 Fix 및 gcc를 비롯한 주요 패키지들이 버전 업 됐다는 것에 만족해야 할 듯 하다. 15.10이라는 버전에 걸맞지 않는다는 의견들도 상당히 있더라. 몇일 써본 봐로도 겉보기에 15.04와 크게 달라진 점은 별로 없어 보인다.

하지만, 우분투를 새로 설치하려는 이들에게는 굳이 우분투 14.04.3 LTS 버전을 설치하기 보다는 많이 안정화됐고 systemd와 같은 새로운 환경에 빨리 적응할 수 있도록 우분투 15.10을 적극 추천하는 바이다.

우분투 15.10 Desktop에서 새로워진 점

Linux kernel 4.2가 탑재되었다. 최신 AMD Radeon GPU 사용자들에겐 희소식일 수 있다. kernel 4.0 이후에 도입된 kernel live patching 기능은 배포판 사용자 들에겐 그리 큰 의미가 있는 것은 아니었다. 어차피 커널 보안 패치는 배포판 서버에서 제공하는 것을 받아야 하니까. 서버 사용자이면서 중요한 커널패치를 실시간으로 적용하고자 할 때는 도움이 된다. 이외에도 Intel Broxton 등 새로운 드라이버들이 새 커널에 많이 포함되었단다.

Unity 7.3.2 데스크탑에서는 주로 Dash쪽 기능들이 개선됐는데 눈에 띄는 부분은 Dash에서 검색한 App을 바탕화면이나 Unity Launcher에 Drag & Drop으로 끌어다 놓을 수 있는 점이다. 그리고, Gnome 3.16에 기반하여 Unity가 동작하는데 대표적으로 Scrollbar가 Gnome Overlay Scrollbar로 바뀌었다. 사실 Unity Scrollbar는 별로 편하다고 생각되진 않았고 굳이 그런데 공들일 필요가 있나 싶겠다는 생각도 있었는데, Canonical이 Upstart를 버린 것처럼 포기할 건 과감히 포기하는 모습은 좋아 보인다. 좀 아쉬운 점은 Gnome 3.16의 패키지들이 모두 Ubuntu 15.10에 Update되진 않았다. 대표적으로 gedit나, Nautilus 파일 관리자가  그것들이다.

이외에도, 개발자들을 위한 Ubuntu Make(umake)가 Android 개발 환경을 비롯해서 다양한 platform과 framework 들을 통합 지원한단다. 우분투에서 Game을 즐기는 이들에게는 Steam Controller가 제공된다는 점도 희소식이 될 것이다. 또한, Persistent Network Interface Name이 도입되어서 eth0 같은 네트워크 인터페이스명 대신 다소 복잡하면서도 영구적인 명칭을 갖게 되었다. 다만, 나처럼 Upgrade한 경우에는 eth0를 그대로 사용하는 듯 하다. VirtualBox에 설치해 보았더니 enp0s3라는 인터페이스가 생겼다. 아래 명령으로 확인할 수 있다.

$ ifconfig

이 밖에, 배경화면을 포함해서, gcc 5.2.1, Firefox 41.0.2, Libre Office 5.0.2.2 등등 수 많은 패키지가 Update 되었다.

한글 패키지와 다솜(dasom) 입력기에 대한 바램

한글 관련 패키지는 언제나처럼 [System Settings] > [Language Support]를 선택하면 설치되는데 fcitx가 기본 패키지로 포함되어 있어서 ibus 대신 쉽게 바꿔 사용할 수 있다. 최근에 우분투 한국 커뮤니티에 다솜 입력기를 정식 출시했던데, 다음 우분투 버전에는 다솜 입력기도 한글 패키지에 포함됐으면 하는 바램이다. ibusfcitx 한글 관련 설정은 우분투 14.10 이후의 방법들을 사용하면 되므로 다시 언급하지는 않겠다.

참고로, 다솜 입력기에서는 한글 마지막 입력 후 마우스 이동시 한글이 따라 다니는 끝 글자 버그를 해결했단다. 고생하신 개발자 분께 감사드린다. 한편으로는, 다른 한글 입력기들의 고질적인 유지보수 문제를 해결하기 위해서 더 많은 사람들이 관심과 참여를 가질 수 있기를 바라고, 혼자서 프로젝트를 끌고 가려고 하지말고 나같은 노친네들보다는 후배들이 많이 참여할 수 있도록 해 주시길 바란다. Mir나 Wayland로 X-Window 환경이 바뀌게 되면 또 다른 노력이 필요할 것이고 미래에도 새로운 기술 환경에 적응해서 살아 남아야 하기 때문이다.

우분투 15.10 Upgrade 후 생긴 자잘한 문제들

우분투 15.10으로 Upgrade하고 나서 우분투로 부팅하면 Unity 로그인 화면이 나타나야 하는데 공포의 black screen이 나타났다. 다시 전원을 끄고 부팅했더니 제대로 나타났다가 또 부팅하면 다시 black screen이다. 그런데, Volume을 좀 키웠더니 다행히 black screen 문제는 공포의 black screen 증상은 아니었다. 우분투 부팅시 북 두드리는 소리가 들렸기 때문이다. <Ctrl><Alt><F2> 눌렀다가 <Alt><F7>을 눌렀더니 로그인 화면이 나타났다. 혹시나 해서 ~/.cache 폴더를 지우고 lightdm을 다시 설치했더니 이 문제가 해결된 듯 했는데 재발하더라. [System Settings] > [Software & Updates] > [Additional Drivers] Tab에서 Nouveau 드라이버를 선택했다가 재부팅 후 다시 Nvidia 드라이버를 선택하고 재부팅했더니 더이상 재발하지 않는다.

이 외에 VirtualBox 5.0.8이 죽는 문제가 있었는데 한번만 생기고 더이상 발생하지는 않고 있다. 그리고 chrome이나 chromium 기동시 기본 브라우저로 설정할지를 계속 물어 보는데 더 이상 묻지 않기를 click하면 된다.

기타 참고 사항

우분투 15.10부터 바뀐 것인지 아니면 chrome/chromium에서 제공하는 기능인지 모르겠는데 다운로드시 다운로드 진행상태가 Unity Launcher의 아이콘에 표시된다. firefox는 안된다.

VirtualBox UEFI 모드 Guest 부팅 문제 해결

이전 게시물에서 해결하지 못했던 문제를 해결했는데, 우분투 14.10 이후 버전부터 VirtualBox에서 UEFI 모드로 Guest를 설치하면 가상머신으로 부팅할 수 없었던 문제가 있었다. 15.10에서도 역시 같은 증상이었는데 구글링해 보니 해결 방법이 있었다. UEFI Shell에서 startup.nsh 스크립트 파일이 있으면 이놈을 먼저 실행하는데 여기에 grubx64.efi path를 넣어 주면 UEFI 모드로도 부팅할 수 있다. VirtualBox나 btrfs 파일시스템의 문제는 아니었다. 다만, 우분투 14.04에서는 별다른 설정 없이도 가능했는데 왜 그런지는 모른다. VirtualBox에서 우분투 설치 iso로 부팅한 후 아래와 같이 startup.nsh를 새로운 가상 머신의 EFI System Partition(ESP)의 / 폴더에 생성해 주고 가상머신을 재부팅하면 된다.

$ sudo mount /dev/sda1 /mnt
$ cd /mnt
$ sudo echo '\EFI\ubuntu\grubx64.efi' > startup.nsh

2015/10/07

Grub과 gdisk를 이용한 Windows UEFI/BIOS 설치 USB 만들기


OS X El Capitan으로 Upgrade하면서 우분투 설치 USB가 잘 동작이 안됐던 문제 때문에 USB를 갖고 놀다가 실수로 USB를 지워 버렸다. 우분투 설치 USB를 다시 만드는 김에 Windows 설치 겸용으로도 사용할 수 있도록 Grub과 gdisk를 이용해서 다시 만들었다.

USB 굽기 Tool을 사용하지 않는 방식의 장점은 USB 용량이 커지고 있기 때문에 저장공간을 최대한 활용할 수 있다는 것이다. All-in-one multi-OS 설치 USB 까지는 아니더라도 USB 1개로 BIOS 방식이든 UEFI 방식이든 가리지 않고 우분투와 Windows 설치가 가능하도록 하려는 것이다. 우분투나 OS X에서는 GPT 파티션이든 Hybrid MBR 파티션이든 어떻게 만들어도 상관없는데 이전 글에서 다룬 바와 같이 Windows는 GPT 파티션에 대한 제약 사항이 많다. 이 때문에 우분투를 비롯한 리눅스는 여러개 배포판 또는 버전을 1개의 USB에 iso 파일로 담으면 되지만, Windows는 1개의 버전만 가능하다. 엄밀히 말하면, 아래의 Windows USB 제약사항 들 때문에 Grub2를 사용할 경우  Windows 1개 버전에 대해서는 UEFI/BIOS 설치가 가능하고 2개의 BIOS용 Windows 버전을 추가할 수는 있다.

Grub2를 이용한 Windows 설치 USB 만들 때의 제약사항
  • 우분투처럼 Windows 설치 iso 파일을 이용하여 직접 부팅할 수는 없다. Windows 설치 파티션에 Windows 설치 iso의 내용물을 모두 복사해야 한다. 뭐 syslinux/isolinux로 가능할 수도 있단다. 다만, 이 경우 3~4GB의 Windows 설치 파일을 모두 메모리에 로딩하기 때문에 메모리 제약사항이 생긴단다.
  • Windows 설치 파일들은 USB 상에서는 반드시 첫번째 파티션에 있어야 하고 FAT 파일시스템을 사용해야 한다. 하드디스크는 상관없는데 USB는 Windows에서 저장장치로 쳐주지 않는다. 단, BIOS 모드로 Windows 설치시에는 Grub2의 drivemap 기능을 사용할 수 있으므로 다른 파티션에 있어도 된다. Grub2의 drivemap은 UEFI 모드에서는 사용할 수 없더라.
  • BIOS 모드로 Windows 설치시에는 GPT 파티션을 인식하지 못한다. 이 때문에 Hybrid MBR 파티션을 사용해야하고 EFI Protetive 파티션을 제외한 나머지 3개의 MBR 파티션을 사용할 수는 있다.
  • Hybrid MBR 파티션을 사용하는 USB는 Windows 설치시에는 문제가 없지만, Windows에서 사용하고자 할 때에는 제약사항이 생긴다. EFI 모드의 Windows는 그나마 GPT 파티션들을 인식할 수 있지만 BIOS 모드의 Windows는 USB 파티션들을 아예 인식하지 못할 수 있다.

gdisk를 이용한 USB 파티션 만들기

위의 Windows USB 제약 사항을 고려하여 아래와 같이 gdisk로 파티션을 나누었다. 당연히, 빈 USB에서 작업해야 하고, GPT 파티션 Table을 먼저 만들어야 한다.

$ sudo gdisk /dev/sdb
[sudo] password for aaa:
GPT fdisk (gdisk) version 0.8.10

Partition table scan:
  MBR: hybrid
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with hybrid MBR; using GPT.

Command (? for help): p
Disk /dev/sdb: 31703040 sectors, 15.1 GiB
Logical sector size: 512 bytes
Disk identifier (GUID): 9D794CCE-5719-43A0-A5A7-D8DFBE8488D3
Partition table holds up to 128 entries
First usable sector is 34, last usable sector is 31703006
Partitions will be aligned on 2048-sector boundaries
Total free space is 2014 sectors (1007.0 KiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048         8390655   4.0 GiB     0700  UWRoot
   2         8390656         8800255   200.0 MiB   EF00  UESP
   3         8800256         8802303   1024.0 KiB  EF02  BIOS boot partition
   4         8802304        17190911   4.0 GiB     0700  UWData
   5        17190912        31703006   6.9 GiB     8300  ULData

Command (? for help): x

Expert command (? for help): o

Disk size is 31703040 sectors (15.1 GiB)
MBR disk identifier: 0x01AEFD5F
MBR partitions:

Number  Boot  Start Sector   End Sector   Status      Code
   1      *           2048      8390655   primary     0x07
   2               8390656      8800255   primary     0xEF
   3               8802304     17190911   primary     0x07
   4                     1         2047   primary     0xEE

Expert command (? for help):
위의 내용은 이미 만들어진 USB 파티션을 보여 준 것인데 이것을 참고하여 파티션을 만들면 된다. 먼저 gpt 파티션들을 만들고 파티션 Tpye code를 위와 같이 지정해 준다. 5개의 gpt 파티션을 만들었는데 필수 파티션은 앞의 1~3의 3개 파티션이다. 1번 파티션이 Windows 설치 파티션(4GB)이고, 2번은 ESP(EFI System Partiton; 200MB), 3번은 Grub BIOS Boot Partition(1MB)이다. 1번이 반드시 Windows 설치 파티션이어야 하기 때문에, ESP로 2번 파티션을 사용하고 있다. 참고로 4번은 Windows Data용 파티션이고 5번은 리눅스 설치 iso들을 집어 넣기 위한 파티션이다.

파티션을 나누고 나서 gparted를 이용하여 파일시스템을 만들어 준다. 1과 2번은 fat32로 format 해야 하고, 3번은 포맷할 필요 없다. 4번은 fat32, 5번은 ext4로 포맷하였다. 

gparted로 포맷하고 나서, 다시 gdisk로 Hybrid MBR 파티션을 만들어 주어야 한다. 참고로, gparted로 포맷한 후 gdisk에서 확인해 보니 Hybrid MBR 파티션이 만들어져 있었다. 하지만, 이것을 사용하면 안되고, 위의 마지막 4개의 파티션과 같이 gdisk에서 gpt 1, 2, 4번 파티션을 Hybrid MBR 파티션으로 새로 만든다. 위에 만들어진 Hybrid 파티션을 보면 4번이 EFI Protective 파티션이 되었음에 주의할 필요가 있다.

결과적으로, 아래와 같이 파일시스템이 만들어졌다. parted/gparted에서는 Hybrid MBR 파티션 정보를 볼 수 없다.

$ sudo parted /dev/sdb print
Model: USB Flash Disk (scsi)
Disk /dev/sdb: 16.2GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags: pmbr_boot

Number  Start   End     Size    File system  Name                 Flags
 1      1049kB  4296MB  4295MB  fat32        UWRoot               msftdata
 2      4296MB  4506MB  210MB   fat32        UESP                 boot, esp
 3      4506MB  4507MB  1049kB               BIOS boot partition  bios_grub
 4      4507MB  8802MB  4295MB  fat32        UWData               msftdata
 5      8802MB  16.2GB  7430MB  ext4         ULData
USB에 UEFI 및 BIOS Grub 설치

UEFI Grub은 파일만 복사하면 되므로 아무 리눅스에서나 작업이 가능하지만, BIOS Grub을 설치하려면 BIOS 모드로 부팅한 리눅스에서 작업해야 한다. BIOS 모드로 설치된 리눅스가 없다면 Virtual Box로 하나 만들어 두는게 좋다.

UEFI Grub 파일들을 우분투 12.04.2 이후의 64bit 우분투 설치 iso에서 USB ESP 파티션(2번)에 아래와 같이 복사한다.

$ sudo mkdir /tmp/mnt
$ sudo mount ~/Downloads/ubuntu-15.04-desktop-amd64.iso /tmp/mnt

$ sudo mount /dev/sdb2 /mnt
$ sudo cp -R /tmp/mnt/EFI /mnt
$ sudo cp -R /tmp/mnt/boot /mnt

BIOS Grub은 아래와 같이하면, 2번 파티션 외에 USB의 MBR Boot Sector와 3번 Grub BIOS Boot Partition에 설치 된다.

$ sudo grub-install --recheck --boot-directory=/mnt/boot /dev/sdb

우분투 설치 iso 파일들을 USB에 복사

우분투 설치용으로도 USB를 사용할 것이기 때문에 우분투 설치 iso들을 아래와 같이 5번 ext4 파티션에 복사하였다.

$ sudo umount /mnt
$ sudo mount /dev/sdb5 /mnt
$ sudo mkdir /mnt/boot-isos

$ sudo cp ~/Downloads/ubuntu-15.04-desktop-amd64.iso /mnt/boot-isos
$ sudo cp ~/Downloads/ubuntu-15.04-desktop-i386.iso /mnt/boot-isos
$ sudo sync

Windows 설치 파일 복사

USB 1번 파티션에 Windows 설치 iso 이미지 파일 내의 모든 폴더/파일 들을 복사한다.

$ sudo umount /mnt
$ sudo mount /dev/sdb1 /mnt

$ sudo umount /tmp/mnt
$ sudo mount ~/Downloads/windows.iso /tmp/mnt
$ sudo cp -R /tmp/mnt/* /mnt
$ sudo sync

Grub Boot Menuentry 설정

아래의 Grub 부트 엔트리를 USB 2번 ESP 파티션의 /boot/grub/grub.cfg에 추가한다. 원래의 grub.cfg 파일을 지우고 새로 만드는 편이 좋다.

$ sudo umount /mnt
$ sudo mount /dev/sdb2 /mnt
$ sudo rm -f /mnt/boot/grub/grub.cfg
$ sudo nano /mnt/boot/grub/grub.cfg

$ cat /mnt/boot/grub/grub.cfg
menuentry "[USB] Ubuntu 64-bit Install" {
   set isofile="/boot-isos/ubuntu-15.04-desktop-amd64.iso"
   loopback loop (hd0,5)/$isofile
   linux (loop)/casper/vmlinuz.efi boot=casper iso-scan/filename=$isofile noprompt noeject
   initrd (loop)/casper/initrd.lz
}

menuentry "[USB] Ubuntu 32-bit Install" {
   set isofile="/boot-isos/ubuntu-15.04-desktop-i386.iso"
   loopback loop (hd0,5)/$isofile
   linux (loop)/casper/vmlinuz boot=casper iso-scan/filename=$isofile noprompt noeject
   initrd (loop)/casper/initrd.lz
}

menuentry "[USB] UEFI Mode Windows 8+ Install" {
   insmod part_gpt
   insmod fat
   set root='(hd0,gpt1)'
   chainloader (${root})/efi/boot/bootx64.efi
}

menuentry "[USB] BIOS Mode Windows Install" {
   insmod part_gpt
   insmod fat
   set root='(hd0,gpt1)'
   drivemap -s (hd0) ${root}
   ntldr (${root})/bootmgr
}
참고로 마지막 "[USB] BIOS Mode Windows Install" 메뉴에서 drivemap은 불필요 하지만, BIOS 모드의 Windows 설치 파티션이 USB의 첫번째 파티션이 아닐때 사용할 수 있다.

Windows 버전에 대한 고려 사항

위의 Grub 부트 엔트리 들 중 "[USB] UEFI Mode Windows 8+ Install" 메뉴엔트리는  Windows 8 이후 버전 들에만 적용된다. Windows 설치 iso 파일에 /efi/boot/bootx64.efi 파일이 추가됐기 때문이다.

Windows에서 UEFI를 지원하기 시작한 것은 Windows Vista 이후이고 64bit 버전에만 적용된다. Windows Vista에서 현재의 Windows 10까지 모든 Windows 버전에서 UEFI Windows Boot Manager로 사용될 수 있는 파일이 있는데 bootmgfw.efi라는 파일이다. 이 파일은 Windows 설치 iso 이미지 안에 포함된 /sources 폴더에 install.wim 파일 안에 포함되어 있다. 이미 다른 PC에 설치된 Windows가 있다면, C:\Windows\Boot\EFI\bootmgfw.efi 파일을 사용해도 된다.

가령, UEFI 모드로 Windows 7을 설치하고자 할 때에는, bootmgfw.efi 파일을 현재 폴더에 복사해 놓았다면 아래와 같이 USB의 Windows 설치 파티션에 /efi/boot/bootx64.efi 파일로 복사해 주면 된다.

$ sudo umount /mnt
$ sudo mount /dev/sdb1 /mnt

$ sudo mkdir /mnt/efi/boot
$ sudo cp ./bootmgfw.efi /mnt/efi/boot/bootx64.efi

설치 USB Test

PC BIOS/Firmware 설정이 UEFI냐 BIOS/CSM 모드냐에 따라 Grub 메뉴에서 UEFI Mode인지 BIOS Mode인지를 확인해서 맞는 놈을 선택해서 부팅해야 한다. 우분투 메뉴는 UEFI/BIOS를 따로 구분하지 않는다. 해당 모드의 Grub이 자동으로 부팅시에 결정되기 때문이다.

Mac PC에서 USB 부팅시 참고사항

Mac에서는 USB를 꽂고 부팅시 <Option> Key를 누르고 있으면 USB Icon으로 부팅 가능한 옵션이 추가되어 표시되는데, 아이콘 밑에 Windows로 표시된 놈은 Windows 부팅 옵션이 아니고, BIOS 모드로 부팅하기 위한 옵션이다. 이 글대로 설치 USB를 만들면 Windows로 표시된 아이콘 외에 EFI Boot로 표시된 아이콘이 두 개가 보인다. 하나는 EFI 모드의 Windows 설치 파티션으로 부팅하고, 하나는 EFI 모드의 Grub으로 부팅되는데 어느 놈이 어느 놈인지 구분할 수 없다. rEFInd에서는 구분이 가능하다. 또한, Windows로 표시된 아이콘을 선택하면 BIOS 모드의 Grub으로 부팅된다.

즉, Mac은 BIOS/Firmware 설정이 따로 없는 대신에 UEFI와 BIOS/CSM 부팅을 동시에 지원한다. Boot Camp가 이 BIOS/CSM 모드를 이용하는 것이고 BIOS/CSM 모드에서는 Hybrid MBR 파티션을 사용한다.

2015/10/04

OS X El Capitan의 Rootless 정책과 Disk Utility에 대하여


이전 글에서 OS X El Capitan Upgrade 후 발생한 문제들에 대해 얘기했는데, 이전 OS X 버전의 Recovery 파티션 두 개를 지워 보려고 하다가 생긴 문제들에 대해서 주로 Disk Utility 사용자 관점에서 정리해 본다. 기본적으로 Disk Utility를 가지고 Recovery 파티션을 지울 수 없었기 때문이다. 이전 글에서도 잠깐 언급했듯이 OS X El Capitan의 새로운 보안 정책인 Rootless(또는 SIP; System Integrity Protection) 때문에 Disk Utility에도 제약이 가해질 수 밖에 없으리란 것은 어느 정도 이해할 수 있지만 본연의 디스크 관리 기능을 제대로 할 수 없다는 것에 대해 왕짜증난다.

Rootless 보안 정책은, 간단히는 root 권한으로도 System의 중요한 설정이나 폴더/파일 들을 건드리지 못한다고 이해하면 되지만, 세부적으로는 매우 복잡한 것 같다. 3rd Party 시스템 관련 앱 개발 회사나 개발자들, 그리고 OS X 서버 사용자들에게는 꽤 부담을 줄 듯하다. 일단, 구글링을 통해 알게된 몇 가지만 정리한다.

Rootless 또는 SIP에 대하여...

Rootless는 com.apple.rootless라는 확장 파일 속성으로 관리하는 것 같고, NVRAM, 프로세스, 폴더, 파일 레벨에서도 통제할 수 있는 듯 하다. 일단, 파일시스템 Protection이 걸려 있는 폴더 들은 /System, /bin, /sbin, /usr(단, /usr/local은 제외) 등 이다. 이 폴더들은 root도 write 권한이 없다. SIP를 관리하는 새로운 Utility가 csrutil이라는 놈이다. OS X Recovery 파티션으로 부팅했을 때에만 SIP를 해제 또는 사용하도록 설정할 수 있다. 다만, 현재 SIP 설정 상태는 언제든지 아래와 같이 터미널에서 확인 할 수 있다.

$ csrutil status

Recovery 파티션으로 부팅해서 Rootless를 해제하고자 한다면 disable, 다시 설정하고자 한다면 enable, 초기 상태(enabled)로 reset하고자 할 때는 clean 옵션을 아래의 예와 같이 주면 된다.

$ csrutil disable

이렇게 Rootless 설정을 바꾸면 재부팅해야 효력이 발생한다고 경고 메시지가 뜬다.

위의 예와 같이 Rootless를 해제하고 OS X로 부팅해서 상태를 확인하면 아래와 같이 뜬다.

$ csrutil status

System Integrity Protection status: disabled.

Configuration:
  Apple Internal: disabled
  Kext Signing: disabled
  Filesystem Protections: disabled
  Debugging Restrictions: disabled
  DTrace Restrictions: disabled
  NVRAM Protections: disabled

위의 각 disabled 된 놈들을 개별적으로 활성화할 수도 있는데, 잘 모르고 사용하면 위험하니까 모르는게 낫겠다 싶다.

Disk Utility의 문제 들

우선, Disk Utility UI가 완전히 바뀌었는데 뭐 Apple 입장에서는 나름 사용자가 쉽게 사용할 수 있도록 바꾸었단다. 파티션을 Pie Chart 모양으로 보여 주는데 보기는 좋으나 마우스 클릭할 공간이 줄어 들었다. GPT 파티션이 기본적으로 128개까지 파티션을 사용할 수 있는데 파티션 수를 20개 이상 사용하는 사용자가 있다면 왕짜증 곱배기가 될 것이다.

기능적으로도 아예 삭제된 기능들이 있는데, Rootless를 도입하면서 삭제된 권한 복구(permissions repair) 기능 외에도, DVD나 RAID 지원 기능이 아예 사라졌다. 사라진 기능들로 인한 불만도 가득하더라.

내가 Disk Utility를 사용하면서 왕짜증나는 문제 들은 또 다른 것들이다. 그것은 본연의 디스크 관리를 할 수 있는 방법이 없다는 것이다.


기본적으로, 전체 파티션을 볼 수 있는 방법이 없다. 물론, 내가 El Capitan에 아직 적응이 안돼서 못찾은 것일 수도 있지만 기존의 방법들이 무용지물이다. 즉, 아래의 터미널 명령으로 Disk Utiltity에서 Debug 메뉴가 생겨서 Hidden Partition까지도 볼 수 있었는데 El Capitan에서는 UI가 바뀌면서 사라진 듯 하다. 기본적으로 보이지 않는 파티션은 ESP(EFI System Partition)와 OS X Recovery Partition이다.

$ defaults write com.apple.DiskUtility DUDebugMenuEnabled 1

위의 화면에서 오른 쪽 Bar Chart를 보면 다른 OS 파티션들이 같이 포함되어 있다. 얼핏 보면 모든 파티션이 다 보이는 듯 하지만 ESP나 Recovery Partition은 아예 없다. 위 쪽의 Partition 명령을 Click하면 Pie Chart가 나타나는데 여기서도 당연히 나타나지 않는다. 참고로, 두 번째와 세 번째 untitled로 표시된 650MB 파티션 두 개는 이전 버전의 OS X Recovery Partiton인데 Mac 부팅시에 안보이도록 gdisk로 파티션 type을 임의로 설정한 것이다. El Capitan의 Recovery Partition이 Mac OS X 파티션 다음에 보여야 하는데 안보이고 맨 첫번째의 ESP 파티션도 안보인다. gdisk에서 Mac OS X 파티션 type은 Apple HFS/HFS+(AF00)이고, OS X Recovery 파티션 type은 Apple boot(AB00)이다. 실제로 3개의 복구 파티션 tyoe code를 gdisk에서 AB00으로 바꾸면 새로운 Disk Utility에서는 3개 파티션이 모두 사라진다. 대신 3개 버전의 OS X Recovery 모드로 각각 부팅할 수는 있다.

그리고, 더 큰 문제는 파티션을 삭제하려면 왼쪽의 Tree 메뉴를 사용해야 하는데 여기에는 기본 OS X 파티션과 Windows 파티션 밖에 보이지 않는다. 리눅스 파티션을 Disk Utility로 지우지 못할 이유가 무엇일까? 이것도 강화된 보안 정책의 일환인가? Windows는 만만해서 파티션을 지울 수 있는 건가? 또한, ESP와 OS X Recovery Partition은 Disk Utility에서 아예 안보이니까 당연히 삭제는 물론이고 아무 것도 할 수 없다.

또 한 가지 문제는 불필요한 Recovery Partition을 삭제하면서 알게된 문제인데 위의 Hidden Partition이 보이지 않음으로 인해 파생되는 문제이다. OS X Upgrade시에 Mac OS X 파티션을 끝에서부터 650MB 정도를 잘라서  Recovery Partition을 새로 추가한다. 나처럼 Mac OS X 파티션이 넉넉하고 3번 Upgrade했다면 3개의 Recovery Partition이 추가된다. 가장 최근에 추가된 놈이 Mac OS X 파티션 바로 옆에 위치하게 된다. 나머지 두 개는 지워도 되는 놈인데 Mac OS X 파티션과 합칠 수는 없다. 중간에 최신 Recovery 파티션이 위치하고 있기 때문이다. 방법은 모든 Recovery 파티션을 삭제하고 새로 최신 Recovery 파티션을 생성해야 하는데 El Capitan에서 가능한지는 더 조사해 보아야 한다. 아무튼, 문제점을 설명하려고 좀 장황해 졌는데, 우분투에서 gdisk를 이용해서 두 개의 Recovery 파티션을 삭제하고 다시 OS X에서 Disk Utility의 Partition 메뉴에서 [-]로 두 개의 빈 파티션을 삭제해 보았다. 중간에 최신의 Recovery 파티션이 El Capitan의 Disk Utility에서 보이지 않음으로 인해 Mac OS X 파티션에 두 개의 파티션이 제대로 합쳐진 것(merge)처럼 보인다. 실제로는 두 개의 파티션이 최신 Recovery 파티션에 합쳐져 있었다.

이 밖에도, OS X Upgrade 시에 OS X 데이터 파티션의 파일 시스템 타입이 hfs인데도 인식하지 못하고 Microsoft Basic Partition으로 바꿔 버린 것과, Rootless를 한번 해제하기 전에는 Disk Utility에서 보여주는 전체 파티션이 Recovery Mode로 부팅했을 때와 OS X로 부팅했을 때 차이가 생겼던 문제도 있었다.

맺음말

OS X El Capitan의 Disk Utility는 여러가지 기능이 삭제되어 불편할 뿐만 아니라, 본연의 디스크 관리 기능을 모두 수행할 수도 없고, 사용자가 의도한 대로 동작하지 않을 수도 있다는 점을 알아 둘 필요가 있겠다.

El Capitan에서 강화된 보안 정책인 Rootless에 대해서도, OS X 고급 사용자나  관리자 입장에서는 어차피 Recovery Mode에서는 모든 root 권한을 여전히 사용할 수 있다는 점에서, 근본적으로 필요한 것이었는지 의구심이 든다. 보안 강화라는 명목으로 3rd Party들을 Apple이 통제하려는 의도일 수도 있다는 생각이 든다.

Apple이 System Integrity에는 그렇게 신경을 쓰면서 Application Integrity에는 소홀해진 느낌~!!!

2015/10/02

OS X El Capitan 설치 후 Ubuntu Grub 복구


새로운 OS가 나오면 무작정 설치하는 안좋은 습관이 있다. 이로 인해 발생하는 문제들도 참 다양하다. 남들보다 먼저 문제를 겪으면 구글링해도 답을 찾기 어려운 경우가 많다. 아무튼 Mac OS X El Capitan Upgrade가 떴길래 걍 설치했다. 우분투로 부팅이 안되는 경우는 이번이 처음은 아니다.

El Capitan Upgrade 후 발생한 문제들

<Option> Key를 눌렀을때 Grub으로 부팅할 수 있도록 해 놓은 것이 작동 안하는 것은 그러려니 한다. 그런데, 하드디스크의 Grub은 물론이고, 전에 만들어 놓은 우분투 설치 USB로도 부팅이 안된다. Windows 10과 새로운 OS X 10.11로만 부팅이 된다. 또, 한가지 문제가 더 생겼는데 OS X 데이터 파티션이 안잡힌다. OS X의 터미널에서 파티션을 확인해 보니 파티션들은 잘 있다.

$ diskutil list

그런데, 가만히 보니 OS X Recovery 파티션이 하나 더 생겼다. 이전 복구 파티션들을 안지웠더니 Recovery 파티션만 3개가 되었다. 문제는 리눅스 파티션이 뒤쪽에 있기 때문에 복구 파티션 하나가 새로 생김으로 인해 파티션 번호가 하나씩 밀려 버린다는 것이다. 당장 예상되는 문제가 Grub 메뉴엔트리의 파티션 번호가 달라지기 때문에 Grub이 당연히 동작하지 않으리란 것이다. 예전에는 리눅스의 /etc/fstab에서도 파티션 번호를 사용했었는데 요즘은 각 디바이스 파티션의 UUID를 사용하기 때문에 리눅스 파일시스템이 mount 되지 않는 문제는 없다.

구세주 rEFInd Boot Manager

아무튼 이 모든 문제를 해결하기 위해서는 어떻게든 우분투로 부팅할 수 있어야 한다. OS X를 새로 Upgrade하면 보통은 rEFInd를 새로 설치해 주면 우분투로 부팅할 수 있다. 그런데, El Capitan에서는 Rootless Mode 라는 새로운 보안 정책이 추가되면서 rEFInd를 설치해도 부트 엔트리에 rEFInd가 추가되지 않는 듯 하다. Rootless Mode라는 것이 얼핏 구글링 한 바로는 root 권한으로도 맘대로 시스템 파일들을 건드리지 못하도록 한단다. OS X Recovery 파티션으로 부팅해서 해제하면 된다는데 아직 모르는 게 많아서 꺼려진다. 쉬운 방법을 선택하기로 했다. rEFInd를 기본 boot loader로 만들어 버리는 것이다.

참고로, rEFInd는 OS가 부팅하기 이전에 부팅하므로 OS dependency가 없다. 어떤 OS 환경이든지 binary 파일들이 같다는 얘기다. 다만, rEFInd 0.8.4 미만 버전의 경우 OS X에서 설치하면 기본 설치 위치가 OS X 파티션이었는데 이후의 버전들은 OS에 상관없이 ESP(EFI System Partition) 파티션에 설치된다. OS X Yosemite 이후 OS X 파티션에서는 rEFInd로 부팅할 수 없단다. 또 한가지 참고할 사항은  rEFInd를 만든 이가 바로 gdisk의 저자라는 것이다.

아래와 같이 ESP를 마운트 한 후, 기본 boot loader인 bootx64.efi 파일을 refind_x64.efi로써 대체한다. 당연히 rEFInd가 설치되어 있어야 한다.

$ sudo mkdir /mnt
$ sudo mount -t msdos /dev/disk0s1 /mnt
$ cd /mnt/EFI/Boot
$ cp -f ../refind/refind_x64.efi ./bootx64.efi

이제 OS X를 재부팅 한 후 <Option> Key를 누르고 있으면 EFI 부트 엔트리가 보이는데 이 놈을 선택하면 rEFInd가 뜨고 다시 부트 엔트리들이 나타난다. 여기서 grubx64.efi를 선택해 봐야 파티션 넘버가 달라져서 우분투로 부팅할 수 없다. rEFInd는 계속 Upgrade되고 있는데 최신 버전에서는 리눅스 커널로 바로 부팅할 수가 있다. 커널로 부팅하려면 rEFInd 부트 엔트리 중에서 다시 rEFInd를 선택하면 된다. 이렇게 두 번 선택하는 이유는 처음에는 기본 부트로더가 된 rEFInd로 부팅한 것이지만 설정 파일(refind.conf)을 읽지 못하기 때문에 ESP 파티션의 boot loader들만 보여주기 때문이다.

최근에 사용했던 리눅스 커널을 선택하니 우분투로 깔끔하게 부팅이 된다.

Ubuntu에서 Grub 복구

우분투로 정상 부팅했으니 아래의 명령만으로도 Grub이 복구될 줄 알았다.

$ sudo update-grub
$ sudo reboot

위의 명령으로 최소한 /boot/grub/grub.cfg의 부트 엔트리들에 있는 파티션 넘버는 교정이 된다. 그런데, 우분투로 부팅이 안된다. 아래와 같이 오류 발생...

Error: unknown filesystem.
grub rescue>

----------------------------------------------------------------------------------------------------------------
참고: grub rescue> 모드에서 우분투로 부팅하기

아래와 같이 grub rescue 모드에서 우분투의 boot 파티션을 알아 낼 수 있다.

grub rescue> ls
(hd0) (hd1) (hd1,gpt1) (hd1,gpt2) ......

grub rescue> ls (hd1,gpt9)/
/boot ......

위와 같이 /boot 폴더가 보이는 파티션이 리눅스 boot 파티션이다. 이제 아래와 같이 하면 Grub으로 부팅할 수 있다.

grub rescue> set prefix='(hd1,gpt9)/boot/grub'
grub rescue> insmod normal
grub rescue> normal
----------------------------------------------------------------------------------------------------------------

이렇게 해서 Grub으로 부팅한 후,

$ sudo apt-get install --reinstall grub-efi
$ sudo update-grub
$ sudo reboot

다시 부팅했으나 역시 매한가지다. grub rescue>....

grub-efi 패키지를 재설치해도 해결이 안되는 걸 보니 혹시 무슨 cache 파일같은 찌꺼기 때문일지도 모른다는 생각이 들어서 우분투로 재부팅한 후,

$ sudo apt-get install grub

하니, grub-efi 패키지를 지우고 db를 갱신하겠냐고 물어본다. 패키지만 설치된 상태에서 Ctrl-c로 빠져 나왔다. 그리고 다시 grub-efi 패키지 설치...

$ sudo apt-get install grub-efi
$ sudo reboot

이렇게 하니까 예전의 우분투 Grub으로 완전히 복구되었다.

그런데, 돌이켜 보면 이전에 정리했던 UEFI Grub 복구 절차만 충실히 따라 했어도 복구되었을지 모른다는 생각이 든다. 위의 내용과 비교해서 빠진 부분이 grub-install 명령 실행 부분인데 이 명령을 사용하지 않았던 이유는 "efibootmgr -v" 명령으로 확인시 우분투 boot entry가 멀쩡히 살아 있었기 때문이다. grub-efi 패키지를 새로 설치하면 grub-install 명령이 자동으로 수행된다. grub-install 명령이 NVRAM에 우분투 boot entry를 등록해 주는 일 외에 파티션 변경에 따른 설정을 추가로 해줄 수도 있기 때문이다.

OS X 데이터 파티션 복구

이제 우분투가 정상이 되었으니 나머지 문제들은 쉽게 처리할 수 있다. OS X 데이터 파티션은 gdisk에서 확인해 보니 Microsoft Basic Data(0700) 파티션으로 파티션 코드가 설정되어 있었다. 이 놈은 Apple HFS/HFS+(AF00) 이었던 놈이다. 코드를 바꿔주고 OS X로 재부팅했더니 데이터 파티션이 제대로 복구되었다.

gdisk에 대한 다른 글 들에서 언급한 바 있지만 서로 다른 OS의 파티션 Tool들을 혼용해서 사용할 경우에는 반드시 gdisk로 파티션 테이블에 변화가 생겼는지 확인해 볼 필요가 있다. Recovery 파티션을 OS X Upgrade시 추가하면서 파티션에 변화가 생긴 것인데 OS X 파티션 조차 몰라 보다니... :-(

각종 부팅 설정 원상 복구

일단 rEFInd도 최신 버전으로 재설치했고, Mac 부팅시 <Option> Key를 눌렀을 때 Grub이 뜨도록 다시 설정하였다. 그리고 부팅 순서도 우분투 Grub으로 먼저 부팅하도록 efibootmgr로 재설정 하였다.

남은 일

우분투 설치 USB로 왜 부팅이 안되는지 알아 볼 필요가 있고, 불필요한 OS X Recovery 파티션도 제거해야 겠다.

(2015/10/06 Update)

우분투 설치 USB로 부팅이 안됐던 이유는 USB에서 gdisk로 Hybrid MBR 파티션을 만들면서 EFI Protective Partition(0xEE)의 위치를 맨 앞이 아니라, 맨 뒤로 바꿨기 때문이었다. 이 상태에서는 Hybrid MBR 파티션 들 중 첫번째 FAT 파일시스템을 ESP로 인식해 버리더라. 이전 우분투 설치 USB 만들기 방법에 문제가 있었던 것은 아니었다.

Grub이 이상해졌네...

그런데, 우분투 15.04 설치 후 Grub이 몇번 update 됐는데 그 때문인지 아니면 El Capitan Upgrade 후에 뭔가 바뀐 것인지 잘 모르겠는데, /dev/sda인 하드디스크를 Grub에서 hd0가 아니라 hd1으로 인식하고 있더라... USB를 꽂은 채로 Grub 부팅시 다시 확인해 보면 USB는 hd0로 인식하고, 하드디스크는 hd2로 인식한다. 그런데, /boot/grub/grub.cfg 파일의 부트 메뉴엔트리에는 하드디스크 hint가 hd0로 되어 있어도 UUID를 먼저 참고하기 때문에 하드디스크로 부팅하는데 문제가 생기지는 않는다. 다만, 하드디스크의 우분투 설치 iso파일로 부팅할 때는 grub.cfg에서 hd0가 hd1으로 바뀌어야만 부팅이 된다. 이 때는 hint가 아니고 정확한 위치를 지정하고 있기 때문이다.

아무튼, Grub이 update 되면서 벌레가 생긴 것인지, 아니면 첫번째 하드디스크를 hd0에서 hd1으로 하기로 한건지, 또는 OS X El Capitan 때문에 발생한 문제인지는 확실하지 않다.

2015/09/12

BIOS GPT 하드디스크를 이용한 Windows 10 Clean Install


이전 글에서는 UEFI를 지원하는 PC에서 Windows 10 Clean Install 한 것에 대해 얘기했었는데, 여기서는 GPT(GUID Partition Table) 파티션을 사용하는 BIOS PC에서 Windows 10 Clean Install 한 것에 대해 얘기해 보려고 한다.

구입한지 5년된  Dell 11" Alienware(m11x)에는 Windows 7과 Ubuntu 외에 Hackintosh를 시험삼아 설치했었다. 결과적으로 Hackintosh 설치 당시에는 m11x가 최신 PC였기 때문에 설치는 했지만 네트웍과 Nvidia 3D 가속이 안돼서 이 후로 쓰지 않고 방치해 놓고 있었다. 참고로, 당시에 성능과 휴대성을 갖춘 노트북으로 Dell 12" 모델이 단종되는 바람에 이 놈을 산 것이었다. m11x  출시 후에 11" Macbook Air가 나왔다. 11인치는 너무 작고 최대 해상도가 1366x768 이라 답답하다. 최근에는 베젤 공간을 없앤 12인치 노트북 모델들이 아마 휴대성과 성능을 겸비한 노트북들이지 않을까 싶다.

아무튼 이 놈은 UEFI를 지원하지 않았기 때문에 Multi-OS를 설치하기 위한 방법을 찾아야 했다. 그 때 찾은 것이 Grub BIOS-GPT 파티션이다. BIOS PC에서 GPT 파티션을 사용하면서 Multi-OS booting이 가능한 방법이다. 이 파티션에 대해서는 "Ubuntu UEFI 모드 설치 USB 만들기"에서도 언급한 바 있다. GPT 파티션을 사용하려면 모든 것을 지우고 새로 설치해야 했기에 위의 USB를 만들어서 작업했었다. 나에게 있어서 OS에 관한 한 항상 모든 문제의 시작은 Windows였고 그 끝도 Windows였다. Windows에서는 아래와 같은 제약 사항이 있는데 당시에는 주로 USB에서 테스트했기에 제약 사항조차 제대로 파악하기 어려워서 매우 헤맸었다.

Windows에서 GPT 파티션 사용시 제약 사항
  • Windows Vista 이후 UEFI를 지원하면서 HDD(하드디스크)에서 GPT를 지원하기 시작했지만, BIOS 모드로 Windows 설치시  GPT 파티션을 인식하지 못함
  • Windows 10을 포함해서 UEFI 환경에서조차 HDD에서는 GPT 파티션을 지원하지만 USB는 1개의 파티션만 인식함
  • 결과적으로, BIOS 모드 Windows 환경에서 GPT 파티션을 사용하려면 Hybrid-MBR 파티션을 사용해야 하나, 여기서도 USB는 1개의 파티션만 인식함
우분투 설치 USB는 UEFI와 BIOS를 모두 지원할 수 있지만, 위의 Windows 제약 사항들 때문에 UEFI와 BIOS를 모두 지원하는 Windows 설치 USB는 만들기가 매우 어렵다. All-in-one Multi-OS 설치 USB를 만들어 보려고 한 사람들이 나 말고도 꽤 있을 것이다. 사실, 아예 불가능한 것은 아니다. USB에 UDF 영역을 별개로 만들어서 Windows 설치 iso를 구우면 USB의 UDF 영역을 CD로 인식하기 때문에 UEFI 환경에서는 UEFI 모드로 부팅하고, BIOS 모드에서는 BIOS 모드로 부팅한다. 다만, 이 영역을 만들기 위해서는 전문적인 USB Tool을 사용해야 한다. 이 USB에 앞서의 USB 만들기 글을 적용하면 All-in-one에 근접한 Multi-OS 설치 USB가 된다. Grub2와 Grub4Dos를 같이 사용하면 All-in-one Multi-OS 설치 USB를 만들 수 있을지도 모른다.

Windows 10 Clean Install 노가다를 다시 시작할 수 밖에 없었던 사연

사실, Windows 7도 훌륭한 OS이다. 전에 Windows 10 설치 노가다를 한 경험이 있어서 다시는 하고 싶지 않은 일이었다. 문제는 애초에 Windows 파티션을 너무 작게 잡은데서 비롯된 것이다.


위의 화면과 같이 WRoot(/dev/sda3) 파티션에 Windows 7을  50GB 할당했었다. 당시에는 넉넉해 보였다. 나중에 알았지만 Windows 7은 Update를 계속할수록 디스크를 갉아 먹는다. 최근에 Update 했더니 여유 공간이 200MB 정도 밖에 없어서 Update 조차 불가능한 상황이 되었다. Windows 7에서 제공하는 디스크 정리 도구를 사용해서 불필요한 시스템 Backup 파일까지 제거해도 1GB 정도 밖에 남지 않았다. 웬만하면 OS 이외의 앱들은 D: 드라이브인 WData(/dev/sda4) 파티션에 설치하는데도 이런 일이 생긴 것이다. 다행히, iTunes를 포함한 Apple 앱들과 Data 공간을 싸그리 지웠더니 6GB정도의 공간이 남았다. Windows 8 이후부터는 Windows Update 후에도 공간을 어느정도 정리해준단다. 하지만, Windows 7은 Update 후 공간이 부족할 때마다 또 다른 노가다를 해야 한다. 이런 상황에서 Windows 10 무료 업그레이드 예약하라고 자꾸 귀찮게 하는 놈이 눈에 띄었다.

Windows 10으로 Clean Install 하면 OS 공간이 대략 18GB밖에 되지 않는다. 그래서 이 참에 이 노가다나 저 노가다나 비슷하다는 생각이 들어서 Windows 10 Clean Install을 결심하게 되었다. 그래서 바로 무료 업그레이드 예약을 해 버렸다. 뭐 10분 정도 지나니까 Windows 10으로 Upgrade하란다. Upgrade 시간이 오래 걸리는 것을 알기 때문에 그냥 Upgrade 걸어 두었다.  Windows Clean Install을 진행하기에 앞서 Upgrade 후에 Windows 정품인증이 됐는지 확인할 필요가 있는데 잘 돼 있더라.

참고로, Windows 10 Upgrade에 필요한 최소 공간이 3GB 정도란다. Windows 10 설치파일 용량 정도이다. 그런데, Windows 10으로 Upgrade 한 후 한달 이내에는 다시 Windows 7으로 복원할 수 있단다. 상식적으로 현재 여유 공간이 6GB 밖에 안남았는데 Windows 7과 Windows 10을 동시에 디스크에 남겨놓을 순 없기에 아마 MS 서버에 Backup을 하는 것 같다. 기존에 설치된 앱들이 많기 때문에 역시나 Upgrade 시간도 상당한 시간이 걸렸다. Windows 10으로 Upgrade를 마치고 나서 OS 공간이 얼마나 남았나 보았더니 똑같이 6GB 정도 남았더라. Windows.old 폴더가 있긴 한데 5GB 정도 밖에 안되고... 이것이 Windows Clean Install을 하지 않으면 안되는 이유이다. Windows 10 Clean Install 후에는 역시 18GB 정도 밖에 OS 파티션을 잡아먹지 않는다.

Windows 10 Upgrade 시에 또 한가지 참고할 점은 기존의 Grub 설정을 건드리지 않는다는 점이다. 즉, MBR 영역을 건드리지 않는다. 하지만, 나중에 Windows 10을 Clean Install 하면 MBR을 덮어 버리므로 Grub을 복구해 주어야 한다.

BIOS 모드에서 GPT-MBR Hybrid Partition 사용

위의 gparted 화면에서 알 수 있듯이 gparted에는 GPT 파티션 순서와 용량 정보는 있지만 Hybrid MBR 파티션 정보는 보이지 않는다. Hybrid MBR 파티션을 만들어 주는 도구는 리눅스에 기본 설치된 gdisk이다. gdisk로 다시 들여다 본 것이 아래의 화면이다.


위의 화면 아랫 부분에 4개의 MBR 파티션이 보인다. 이 파티션들은 gdisk의 "recovery and transformation options (experts only)" 메뉴에서 "make hybrid MBR" 메뉴를 이용해서 만든 것이다. 기존에 생성한 GPT 파티션 중에서 MBR 파티션에 어떤 놈을 보여 줄지를 지정하면 된다. 단, MBR 파티션은 Windows에서 사용하는 파티션이므로 vfat 또는 ntfs 파티션이어야 한다. gdisk의 GPT 파티션 상에서는 code가 0700(Microsoft Basic Data)인 놈들 중에서 골라야 한다. Hybrid-MBR에서는 EFI Protective Partition이 기본적으로 필요하기 때문에 실제로 사용자가 사용할 수 있는 파티션 갯수는 3개까지이다. 위의 화면에서 0xEE는 gdisk가 자동으로 지정한 파티션이다.

gdisk가 좋은 점은 파티션에 별짓을 다했다가도 "write table to disk and exit" 명령만 사용하지 않으면 실제로 파티션 변경이 일어나지 않는다는 것이다. "quit without saving changes" 명령으로 빠져 나오면 안전하다.

gdisk를 이용한 파티션 재구성

Windows 10을 Clean Install 하기로 한 마당에 더이상 사용하지 않는 Hackintosh 파티션인 MRoot(/dev/sda2)를 WRoot 파티션과 합쳐서 Windows OS 공간을 늘리기로 했다. 또, Grub에서 사용하는 BIOS boot partition(/dev/sda10)이 sector 순으로 보면 /dev/sda3가 됐어야 하는데 맨 나중에 생성하는 바람에 10번째 파티션이 되어 버린 것도 gdisk의 "sort partitions" 메뉴를 이용해서 재정렬할 필요가 있었다. 이것 때문에 gparted 실행시 경고 메시지가 뜬다.

그런데, 이 시점에서 Windows 10 설치 USB를 다시 만들어야 하는 문제가 있었다. 예전에 만들어 놓은 USB는 우분투 설치 USB에 함께 들어 있어서 Grub2에서 UEFI 모드로만 동작하기 때문이다. 별개의 USB를 사용하기 보다는 HDD에 4GB의 Windows 10 설치 파티션을 따로 만들어서 설치 iso의 파일들을 모두 복사해 놓고 Grub2를 사용하면 HDD를 이용해서 Windows를 설치할 수 있겠다는 생각이 들었다.

위의 고려 사항들을 종합해서 결과적으로 아래 화면과 같이 파티션을 재구성하였다. 파티션 재구성 작업시에는 앞서 만든 우분투 설치 USB로 부팅해서 작업해야 한다.


기존의 Grub BIOS 파티션을 지우고 EFI System Partition(ESP) 다음에 새로 만들었다. 그 다음에는 Windows 10 설치 파티션(WInst)을 만들고, 그 다음에 WRoot 파티션을 다시 만들었다. 파티션 재 구성시 주의할 점은 기존의 중요한 Data 파티션 들과 우분투 파티션은 건드리면 안된다는 것이다. 우분투 파티션은 Grub을 이용해서 Windows 10 설치 파티션으로 부팅시 사용해야 한다. 참고로, BIOS 모드에서는 ESP 파티션을 만들 필요는 없다. 다만, 공간도 그리 많이 차지하지 않고 UEFI 환경과 비슷하게 만들어 사용하는 것이 좋은 습관이 될 듯해서 그냥 둔 것이다.

gdisk에서 파티션을 생성한 후에 gparted를 사용하여 WInst와 WRoot 파티션을 ntfs로 포맷하였다. 아예 gparted로 파티션 작업을 할 수도 있겠지만 gdisk가 세부 정보를 보여 주기 때문에 편리한 점이 있다. 포맷을 완료 한 후에 gdisk에서 아래 화면과 같이 Hybrid MBR 파티션을 지정해 주어야 한다.


gdisk와 gparted 또는 다른 OS의 partition tool을 혼용해서 사용할 경우에는 항상 gdisk로 파티션 table에 변경사항이 없는 지 확인해야 한다. 실제로, gdisk에서 Hybrid MBR 파티션을 생성하고 나서 gparted에서 ntfs 파티션 포맷만 하더라도 Hybrid MBR 파티션 정보가 날아가 버린다. 이 정보가 날아가면 BIOS 환경에서 Windows로 부팅할 수 없게 된다.

또한, 위의 경우와 같이 Grub BIOS 파티션을 새로 생성하는 경우에는 우분투 파티션의 BIOS Grub을 다시 설치해 주어야 우분투로 부팅할 수 있다. Grub 재설치 방법은 이전 글인 "Ubuntu BIOS 및 UEFI Grub 복구"를 참고하면 된다.

Grub2와 HDD의 Windows 설치 파티션을 이용한 Windows 10 설치

우분투 설치 USB에서 파티션을 재구성한 후 우분투로 부팅해서 Windows 10 iso의 파일들을 WInst 파티션에 모두 복사한다. 그리고 나서, update-grub 하면 자동으로 Windows  Recovery 메뉴엔트리가 Grub에 추가된다. 참고로 우분투 14.04 환경이다. 이전 버전에서는 자동으로 안될 수도 있는데 이 때에는 수동으로 Grub menuentry를 /etc/grub.d/40_custom 파일에 만들어 주고 update-grub을 해 주어야 한다.

$ sudo update-grub
$ sudo reboot

재부팅 후 Windows Recovery 메뉴로 부팅해서 Windows 10 Clean Install을 진행하면 된다. Windows 설치 자체는 뭐 큰 어려움이 없다. 다만, 설치시에 설치할 파티션을 WRoot 파티션으로 지정해 주어야 한다.

Windows 10 설치 후 WInst 파티션은 D: 드라이브로 잡혀 있다. 이 놈은 숨겨 두는게 좋은데, 디스크 관리자에서 드라이버 문자만 제거해 주면 된다.

Windows 10 설치 후 Driver 문제

Windows 7에서 10으로 Upgrade 한 상태에서는 모든 Driver가 정상 동작했었는데 Windows Clean Install 후에 제어판의 장치관리자에서 확인해 보니 Video 드라이버도 기본 저해상도 드라이버로 잡혀 있고, 알 수 없는 장치로 표시된게 대부분이었다. 혹시나해서 드라이버 업데이트를 On-line에서 검색해서 설치하도록 했는데 대부분 잘 잡아 준다.

참고로, Dell 사이트에서는 m11x 드라이버는 Windows 7 밖에 지원하지 않는다. 그리고, Windows 7 드라이버의 설치 프로그램이 Windows 10에서는 아예 실행되지 않는다. 일단, 알수 없는 장치 두 개는 드라이버 업데이트를 할 수 없었고  Bluetooth도 안잡혀 있었다. Bluetooth는 Dell site에서 Windows 10을 지원하는 Bluetooth 4.0 드라이버를 다른 랩탑 모델 다운로드 사이트에서 시험삼아 설치해 봤는데 잘 된다. 알 수 없는 장치는 장치관리자의 상세 정보를 이용해서 구글링해 보니까 키보드 콘트롤 드라이버하고 낙하센서 드라이버인 듯 하다. 이외에도 키보드 LED Backlight 를 비롯한 LED 제어 드라이버도 필요하긴 한데 PC 쓰는데 큰 지장이 있는 것들은 아니어서 그런대로 만족이다.

Grub 복구

Windows를 설치하고 나서 우분투를 다시 사용하기 위해서 우분투 설치 USB로 다시 부팅해서 Grub 복구 작업을 다시 해 주어야 한다. "Ubuntu BIOS 및 UEFI Grub 복구"를 참조하면 된다.

노가다 소감

Windows 7 디스크 공간 문제 때문에 Windows 10 Clean Install 노가다를 했는데 그런대로 만족이다. 어차피 파티션 정리작업을 한번쯤 하려고 했었기 때문에... 더구나, BIOS GPT 환경에서 Hybrid MBR을 사용하는 유일한 PC이기도 했기 때문에 잊어버리기 전에 다시 여러가지 문제들을 정리할 기회가 되기도 했으니까.

보통 OS 설치시 USB를 많이 사용하는데 HDD를 사용해서 Windows를 설치하는 것도 괜찮은 방법인것 같다. 더구나 BIOS GPT 환경에서는 Windows의 제약 사항때문에 무척 편리한 방법이라는 것도 새삼스럽게 느껴진다.

2015/08/09

Windows 10과 Ubuntu Unity Desktop


Windows 10을 몇일 써 보니 Ubuntu Unity Desktop과 겉보기에는 다르지만 근본적으로는 비슷한 기능들이 보여서 사용자 관점에서 간단히 비교해 보기로 하였다. 사실, OS 들도 서로 모방하면서 발전하는 경향이 있기 때문에 단순히 우분투나 리눅스가 더 낫다고 주장하려는 것은 아니다.

Windows 8과 우분투 Unity Desktop - 사라진 "시작 메뉴"

Windows 8에서 Windows Tile의 등장으로 Windows Desktop은 Windows 앱 중의 하나로 전락했다. 더구나 Windows Desktop으로 진입한 후에도 "시작 메뉴"에 자신이 설치한 앱들이 나타나지 않는 것이 많은 사용자들을 당황하게 만든 것 같다. 오른쪽 위 언저리에 마우스를 갖다 대야 나타나는 앱 검색 기능은 Windows 8을 직접 설치한 사람이 아니라면 사용 방법도 모를 것이다. 사실, Windows 8을 설치하고 나서 Gnome Shell을 모방한게 아닌가 하는 생각이 들었었다. 우분투 Unity도 Gnome Shell과 Mac OS X 짬뽕인 것처럼 느껴지듯이...

"시작 메뉴"의 기원은 Windows 였고, "시작 메뉴"를 Desktop에서 처음 없앤 것은 Gnome Shell이었을 것이다. 우분투의 Unity Desktop에도 "시작 메뉴"가 없다. Windows 7까지의 Desktop 환경에 익숙한 사용자들은 마우스로 자신이 설치한 앱을 "시작 메뉴"에서 찾아 사용하던 습관을 버리기 어렵다. "시작 메뉴"가 사라진 Windows 8과 마찬가지로 우분투 Unity Desktop도 처음 우분투를 접하는 사용자들에게는 거부감을 줄 수 있다. 리눅스 Mint 사용자들이 우분투 사용자 보다 늘어나게 된 주요 원인 중 하나도 "시작 메뉴" 때문일 듯 하다. 더구나 "시작 메뉴"는 키보드에 [Windows] key가 배치되면서  더욱 사용자들에게 익숙해져 버렸다. 리눅스 Desktop 환경에서도 이 [Windows] key를 [Super] key로 사용하기 때문에 "시작 메뉴"는 Windows 사용자뿐만 아니라 리눅스 데스크탑 사용자들에게도 익숙한 것이다.

키보드가 있는 PC 환경에서는 "시작 메뉴"에서 마우스로 앱을 찾아 들어가 클릭하여 실행하는 것보다는, Gnome Shell이나 Unity Desktop에서 처럼 [Super(Windows)] key를 눌러서 앱이나 파일을 키워드로 검색하여 실행하는 것이 훨씬 효율적이다. Windows 8이나 우분투 Unity Desktop이 Touch 환경까지 고려해서 만든 것이지만, 키보드가 없는 Touch Pad 환경에서는 키워드 검색보다는 Touch로 "시작 메뉴"의 앱을 찾아 들어가 실행하는 것이 더 나을 수 있다.

그러나, Windows 8이나 Unity Desktop이나 "시작 메뉴"는 사라졌다. 그렇다고 Touch가 불가능한 것도 아니다. Windows 8에서는 앱들이 Tile에 배치되고 Unity Desktop에서도 Unity Launcher나 Dash에서 앱 아이콘을 Touch 할 수 있다. 그러나, 익숙한 카테고리 별로 앱들이 분류된 "시작 메뉴"와는 달리 일일이 원하는 앱을 찾기는 무척이나 힘들다.

Windows 10 "시작 메뉴" 부분 복귀와 우분투 Unity Desktop - 검색 기능

Windows 10에서는 부팅 후 Desktop이 기본 환경이 되었고 "시작 메뉴"도 부분적으로 부활했다.  Windows 7까지의 "시작 메뉴"와는 달리 카테고리가 알파벳 또는 가나다 순으로 배치되었다. 자주 사용하는 앱은 "시작 메뉴"의 Tile에도 배치할 수 있도록 Windows 8의 Tile 기능을 수정했다.

그렇지만, 자신이 설치한 앱이 "시작 메뉴"에 바로 나타나지 않기 때문에 "시작 메뉴" 복귀를 원했던 사용자들은 여전히 실망할 것이다. 참고로 "시작 메뉴"에서 모든 앱 보기로 가나다 순으로 배치된 앱을 찾아서 Tile에 앱 아이콘을 끌어다 놓으면 "시작 메뉴"의 Tile에 자주 사용하는 앱을 배치하는 것이 그리 어려운 일은 아니다. Tile 내에서도 수직으로 아이콘을 Tile이 없는 곳에 조금 더 밑으로 끌어다 놓으면 새로운 카테고리도 등록할 수 있다.

Windows 10에서 이 보다 더 주목할만 한 것은, 앱/설정/파일 검색기능을 "시작 메뉴" 및 Task bar에 배치함으로써 키워드 검색 기능을 Windows 8보다 더욱 강화시켰다. Windows 8에서는 검색기능이 숨어 있다는 점 외에도 사용자가 앱/설정/파일을 별도로 지정해서 검색해야만 원하는 결과를 얻을 수 있었지만, Windows 10에서는 인터넷 검색까지 포함해서 통합 검색 결과를 보여준다. 이는 우분투 Unity Desktop의 검색 기능과 거의 유사하다고 볼 수 있는 것이다.


하지만, Windows 10의 키워드 검색 기능은 다음과 같이 우분투 Unity Desktop/Gnome Shell 보다는 아직 한 수 아래다.
  • 앱 사용 목적에 따른 키워드 검색 지원이 안된다. Unity Desktop에서 "internet" 또는 부분 문자열인 "int"로만 검색해도 인터넷과 관련된 앱들을 보여주는데, Windows 10에서는 internet이라는 단어가 들어간 앱인 internet explorer만 검색된다.
  • 또한, 최근에 만든 문서 검색은 키워드 검색 후 [내 장치]에서 검색을 한번 더 선택해야 보여 준다. 탐색기에서 최근에 사용한 문서나 폴더를 볼 수도 있기는 하다. 하지만, Unity에서는 통합 검색 결과를 사용자들에게 유용한 형태로 보여준다.
  • 추가적으로, Windows에서는 파일 확장자 별로 기본 앱이 할당되어 있음에도 확장자로 검색하면 기본 앱을 보여주지 않는다. Unity는 확장자 검색도 지원된다. 가령, ppt를 검색하면 ppt 파일 뿐만아니라, Libre Office Impress도 검색된다.
이 외에도 한글 키워드 들이 제대로 동작하지 않는 것은 Unity나 Windows 10이나 비슷하다고 볼 수 있다. 가령, "word"로 검색하면 Office Word가 검색되지만, "워드"로 검색하면 워드패드만 검색되는 식이다. Windows 10의 키워드 검색 기능이 우분투보다 좋은 한 가지는 구글 검색처럼 한글 변환키를 누르지 않은 상태에서 한글 키워드 검색이 가능하다는 점이다. 가령, "메모" 대신 "apah"라고 검색해도 메모장을 보여주는 식이다.


참고로, 우분투 Unity에서는 Lens 확장 기능을 이용해서 야릇한(?) 것들에 대한 검색도 지원한다. 구글 검색에서 시도하는 것들을 다 집어 넣으려는 것인지 모르겠지만... 가령, 우분투 15.04의 Unity에서 "10*300"을 검색하면 계산기 앱을 띄워서 "3000"이라는 결과를 보여준다. 뭐 이런 것까지 지금 당장 필요해 보이지는 않지만 미래의 OS에는 야릇한 기능 들이 일상 기능이 될지도...

결론적으로, 우분투 Unity Desktop에서는 "시작 메뉴"가 없어도 키워드 검색만으로 충분하지만, Windows 10은 좀더 개선할 필요가 있다.

Windows 10 가상 데스크탑과 우분투 작업공간

Windows 10에서 처음으로 가상 데스크탑을 지원하기 시작했다. 가상 데스크탑의 수는 Gnome Shell처럼 동적으로 늘렸다 줄였다 할 수 있는 것이 특징이다. Taskbar의 검색 기능 바로 옆에 새로운 아이콘이 하나 생겼는데 이것이 가상 데스크탑 아이콘이다. 물론 Windows 3.1 시절부터 가상 데스크탑을 만들어 주는 앱들을 사용할 수는 있었지만 OS에서 지원하는 것이 아니다 보니 성능이 떨어질 수 밖에 없었다.


반면에 리눅스에서는 X-Window 초기 시절 부터 Workspace라는 이름으로 존재해 왔다. 거슬러 올라가면 리눅스의 Workspace도 Unix를 모방한 것이다. 우분투의 경우에는 [All Settings] > [Appearance] > [Behavior] Tab에서 [Enable workspace] checkbox에 설정을 해 주어야 Unity Launcher에 4분할 작업공간 icon이 나타난다. 작업공간 갯수는 4개가 기본이지만 더 늘릴 수도 있다.

리눅스 데스크탑에서는 각 작업공간에 실행 중인 앱을 마우스로 이쪽에서 저쪽으로 쉽게 Drag & Drop이 가능하다. Windows 10에서도 가능하긴 한데 좀 불편하다. 큰 창에 있는 앱을 화면 아래의 원하는 곳의 작은 가상 데스크탑으로 끌어다 놓아야 한다.


한편으로, Windows의 가상 데스크탑들은 현재 실행 중인 앱 정보가 데스크탑 별로 보안이 잘 유지된다. 우분투에서는  Unity Launcher에서 전체 Workspace에서 실행 중인 앱들을 어느 Workspace에서나 볼 수 있다. 우분투의 장점은 Workspace의 위치에 상관 없이 앱 전환을 빠르게 할 수 있는데 반해 Workspace 간의 실행 앱들에 대해 비밀 보장이 안된다. 뒤집어 얘기하면 Windows 10의 가상 데스크탑의 장점은 한쪽에서 게임을 하다가 다른 데스크탑으로 재빨리 이동하면 다른 사람들에게 들키지 않을 수도 있다는 말이다.

Windows 10 Edge Browser

우분투도 webbrowser라는 Qt 기반의 가벼운 자체 Web browser를 제공하고 있는데 공식적으로 자랑하고 있지는 않고, 기능도 그다지 좋은 편은 아니라서 Windows 10의 새로운 기본 Web Browser인 Edge와 비교하기는 좀 그렇다.

Edge는 잘 알려진대로 ActiveX를 지원하지 않고 타 Web Browser 들에 비해 성능도 무척 좋다. 한편, 각종 정보가 Edge를 통해 Microsoft로 새나갈 수 있다는 얘기도 있다. 다른 Browser에서 볼 수 없는 한가지 새로운 기능이 있는데, 특정 Web에 접속한 후 메모를 하고 저장할 수 있다. Screenshot으로 메모를 쉽게 저장할 수 있는 점은 유용해 보인다.

맺음 말

Windows 10과 우분투 Desktop 중 유사한 기능 들에 대해 간단히 비교했는데 누가 더 낫다기 보다는 이런 기능도 각각 필요해 보인다는 정도로 이해하면 될 것이다.

종합적으로는 Windows 10에서 키워드 검색기능이 더 보완되면 "시작 메뉴"가 더이상 필요하지 않을 수도 있다는 점을 강조하고 싶고, 우분투 사용자들에게는 이미 사라진 "시작 메뉴"에 연연해 할 필요가 없다는 점을 알려 주고 싶다.

2015/08/02

Windows 10 Clean Install


Windows 10을 Clean Install 해 보았다. Windows 7 Home Edition을 사용하던 낡은 PC에서 Windows 8 Pro 버전을 Upgrade promotion 기간에 저가에 샀는데 Upgrade했다가 다시 Windows 7으로 재설치해서 방치하고 있는 license key가 있었는데 낡은 PC를 버리게 돼서 우분투가 설치된 다른 PC에 Windows를 설치하는 김에 따끈따끈한 Windows 10을 설치하기로 했다.

구글링해 보니 Windows 8을 clean install 하고 registry를 수정하면 Windows 8 Upgrade 버전의 license key로 정품인증이 가능하단다. 또, Windows 7이나 8은 설치 후 최신 update를 모두 해 주어야 Windows 10으로 upgrade가 가능하단다. 그런데 Windows 8.1은 바로 Windows 10으로 upgrade 할 수 있단다.

Windows 10 license 정책 변화

추가적으로, Windows 10의 라이센스 정책이 하나의 license를 하나의 특정 기기(main board 기준)에 영구히 종속시키는 정책으로 바뀐 듯 하다. 이는 이전 Windows에서 1개의 license key를 갖고 있으면 아무 PC에나 1개의 Windows를 설치할 수 있었던 license 정책을 바꾼것이다.

이 정책의 좋은 점(?)은, Windows 7, 8, 8.1 이 정품 인증된 PC에서 먼저 Windows 10으로 upgrade한 후에는 같은 기계에서 라이센스 키를 재입력하지 않아도 Windows 10을 영원히 재설치 할 수 있다는 것이다. 이는 특정 PC의 main board 정보와 그 PC에 설치된 Windows license key를 Microsoft사의 서버에서 지속적으로 관리하겠다는 의도인것 같다.

나쁜 점은, 기존에 Windows license가 없는 경우에는 Windows 10 license key를 재구매 하면 되는데, 한번 특정 PC에 설치하면 다른 PC에서는 이 license key를 사용할 수 없게 되는 것이다. 아마도 이것이 기존 Windows 사용자들에게 Windows 10 upgrade를 무료로 제공하는 가장 큰 이유일 듯 싶다. PC가 망가지면 무조건 Windows를 새로 구입해야 하니까...

중장기적으로 이 정책이 Microsoft에게 더 많은 이익을 줄 것임이 분명하다. 그니까 사용자입장에서는 Window 8.1까지 정품 구매한 Windows는 보물로 간직하라는...?

Windows 10 Clean Install 설치 절차

Windows 10을 Clean Install 하기 위해서는 반드시 한번은 기존의 Windows 7~8.1을 Windows 10으로 먼저 Upgrade해 주어야 한단다. M$가 공짜로 Windows 10을 제공하는데 그 정도 노가다야 니들이 해야하지 않겠냐고 생각할지도... 아무튼 Windows 10을 clean install 하기 위해서는 아래와 같이 엄청난 노가다와 소모 시간이 나를 기다리고 있다. 정말 큰맘 먹지 않으면 clean install은 포기하라는...

0. Backup

항상 OS를 Clean Install 하기 전에 중요한 Data를 Backup해 두어야 한다. 더구나 OS 파티션은 삭제하거나 최소한 새로 format 할 것이기 때문이다.

1. Windows 8.1 Clean Install 후 정품 인증

Windows 8.1 Pro 설치 iso를 내려 받아서 rufus로 USB에 구워서 clean install 했다. 그런데, Windows 8/8.1은 Windows 7이나 Windows 8 Upgrade license key로는 설치할 수 없으므로 여기 게시물을 참고해서 ei.cfg 파일을 만들어 설치 USB에 넣어 줌으로써 설치시 license key 입력창이 뜨지 않도록 해 줄 필요가 있다. 다행히도 Windows 8.1 설치 후  license key를 입력했더니 정품인증이 바로 되더라. Registry는 건드리지도 않았는데 말이다.

2. Windows 10으로 Upgrade

Windows 8.1 제어판에서 Windows update를 사용하면 바로 Windows 10  Upgrade가 뜨더라. Windows 10 iso를 먼저 내려 받아서 USB에 구워서 Upgrade 할 수도 있다는데 그냥 제어판에서 Upgrade했다. 내려받는 속도가 빠른 편이라 문제 없었다. 다만, 기존의 Windows 8.1을 backup하는 등의 일을 처리하는 때문인지 Windows 10으로 upgrade 완료하기까지 시간을 정확히 측정하지는 못했는데 1~2시간 걸린듯. 첨에는 내려 받기가 끝나고 나서 설치 준비중이라고 메시지가 뜬 후 한참동안 작업 진행 표시가 없어서 먹통이 됐나부다 했는데 구글링해 보니 원래 시간이 오래 걸리는 것이었다. Upgrade 완료 후 Windows 10이 정품인증 됐음을 확인했다.

Windows 8/8.1에서는 Windows OS 파티션 앞에 Microsoft Reserved Partition을 추가하는데, Windows 10 upgrade 후에는 Windows OS 파티션 끝에 파티션이 하나 더 추가 된다. 아마도 backup 용 인듯...

3. Windows 10 Clean Install

위의 Upgrade 중에 Windows 10 Pro iso(기존 Windows license와 일치하는 Windows 10 버전)를 다시 내려 받아서 USB에 구우면 된다.  설치시에 라이센스 키 입력하는 것은 모두 건너 뛰면 된다. Windows 8/8.1 설치와는 달리 license key를 입력하지 않아도 Windows 10은 설치할 수 있다. 설치 시간은 Windows 8.1 설치시간과 비슷하다. 대략 30분... 설치 후 정품인증이 됐나 확인해 보니 자동으로 정품인증이 되어 있다.

Windows 10 Clean Install 후에는 Microsoft Reserved Partition 1개만 생성되는데 Windows 8/8.1에서 128MiB 였는데 16MiB로 용량이 줄었다.

4. 기존 Windows Software 모두 재설치

자주 쓰던 프로그램들을 모두 재설치 해야만 한다. 걍 천천히 할 생각이다. Windows 10이 기존 Windows 들에 비해 좀 빠릿빠릿 해졌다는 것으로 위안을 삼으면서....

Ubuntu Grub 복구

늘 그랬듯이 Windows를 설치하고 나면 우분투 grub을 복구해야만 다시 우분투로 부팅할 수 있다. 참고로 Ubuntu와 Windows 모두 UEFI 모드로 설치했다. 복구 방법은 이전 글 "Ubuntu BIOS 및 UEFI Grub 복구"를 참고하면 된다. Windows 10 설치 후 우분투 설치 USB에서 UEFI Grub 복구방법이 불완전했기에 이전 글을 수정하였다.

설치 후 소감

아직 Windows 10을 제대로 써보지 않아서 노가다 후 피로감에 빠져 있다. 시작 메뉴 회귀와 함께 우분투 Unity의 검색기능과 동일하게 Task Bar에 앱/파일/키워드 검색 기능이 들어 간것은 인상적이다. Windows 8에도 앱 검색기능이 있었는데 키워드 검색이 잘 안돼서 그닥 쓸모 없어 보였는데 Task Bar에 붙여 놓고 키워드 검색도 되니 한결 쓸모 있어 보인다.

리눅스 사용자들에게는 식상한 가상 작업공간도 새로운 기능인데 나름 빠릿빠릿 동작한다. 이외에도 Cloud 관련 기능들이 눈에 띈다. OneDrive나 OneNote가 그것들이다.

아무튼 기존 Windows 사용자들에게 Windows Clean Install을 권하고 싶지는 않다. 엄청난 노가다와 시간을 허비할 만큼의 가치가 있는 일인지는 잘 모르겠다. 1 PC당 1 license라는 Windows license 정책 변화도 사용자들에게 risk가 있다. PC가 망가지면 새로 license를 구매해야 한다.

결과적으로 우분투를 더욱 더 사랑하게 될 것 같은 느낌이 든다.

2015/05/31

Fedora 22 설치 소감


이전 글에서 리눅스 배포판 들은 도찐개찐이라고 했지만, 지난 주에 Fedora 22가 출시되었다길래 Virtual Box에 설치해 보았다. 우분투를 주로 쓰다보니 페도라를 언제 썼었는지 기억이 가물가물하다. 중간에 CentOS는 좀 사용했었다. 페도라가 리눅스 배포판 중 bleeding-edge인지는 잘 모르겠지만 최신 S/W 들을 빨리 채택하는 것은 틀림없다. Redhat이 페도라에서 검증된 것들을 수용한다는 점과 리눅스의 새로운 기능(기술?)들을 페도라에서 빨리 접해 볼수 있다는 점은 리눅스 사용자들에게 고무적인 일이다.

Fedora 22가 땡겼던 이유...

Gnome Shell 3.16이 뭐가 달라졌나 궁금했고, kernel 4.0에서 live patching이 잘 동작하는지 보고 싶었다. 그리고, Wayland가 탑재되어 있어서 한번 써보고 싶었다. 부가적으로 가상 Desktop 환경인 Vagrant 도 궁금했고, 패키지 관리자로써 Yum을 버리고 DNF를 본격적으로 채택한 점도 눈에 띄었다. 페도라 업그레이드에 대한 세부 사항은 여기를 참고하면 된다.


설치시 문제

그런데, Wayland나 Vagrant는 VirtualBox에서는 테스트 해 볼 수가 없다. 그래서 iMac에 설치해 보려고, 하드디스크의 Fedora 설치 iso를 가지고 부팅했는데 우분투와 마찬가지로 WIFI가 당장 동작하지 않았다. 당장 유선랜을 쓸 수 있는 환경이 아니어서 iMac에 설치하는 것은 보류할 수 밖에 없었다.

설치시에 페도라가 우분투보다 안좋은 점은 non-free 드라이버가 설치 iso에 아예 들어있지 않다는 것이었다. 더구나, 설치 파일들이 통째로 sqashfs 이미지 파일에 들어 있는데 알고 보니 패키지로 구성되어 있는게 아니었다. 걍 페도라가 설치된 채로 sqashfs에 들어 있었다. 설치 iso로 설치한다 뿐인지 실제로는 sqashfs 이미지를 풀어서 하드디스크에 복사해 넣은 다음 필요한 설정만 설치 패키지에서 잡아 주는 형태다.

설상가상으로 페도라는 네트워크이 안되면 설치하지 말라고 얘기할 수 밖에 없다. Broadcom WIFI 드라이버를 일단 VirtualBox의 페도라에서 내려 받아 보려고 했는데 Fedora 22 버전은 아직 올라와 있지도 않았다. Fedora 21 버전에 대한 non-free 드라이버를 사용해도 될 것 같긴 한데 이런 방법은 패키지 의존성 문제가 생길 수 있으니 사용하지 말란다. 소스를 컴파일 하는 방법도 생각해 봤는데 기본적으로 gcc 패키지도 설치되어 있지 않기 때문에 네트워크가 안되면 별로 해볼 수 있는 방법이 없다. 뭐, VirtualBox에서 컴파일해서 iMac에 복사하는 방법도 있지만 귀차니즘이 밀려와서 관두기로 했다.

하드디스크의 Fedora 설치 iso로 부팅하기 위한 Grub 메뉴

나중에 iMac에 페도라를 설치할 수도 있기 때문에 헤맸던 것을 정리해 둔다. 우분투의 Grub에 아래와 같이 메뉴 엔트리를 추가하면 우분투 파티션에 있는 페도라 설치 iso를 이용해서 부팅할 수 있다. 아래 내용을 /etc/grub.d/40_custom 파일에 추가한 후,

$ sudo nano /etc/grub.d/40_custom

menuentry "HDD Fedora 64-bit iso" {
    set isoname="Fedora-Live-Workstation-x86_64-22-3"
    set isolabel="Fedora-Live-WS-x86_64-22-3"
    set isofile="/boot-isos/${isoname}.iso"
    loopback loop (hd0,9)/$isofile
    linux (loop)/isolinux/vmlinuz0 iso-scan/filename=${isofile} root=live:CDLABEL=${isolabel} rootfstype=auto ro rd.live.image quiet rhgb rd.luks=0 rd.md=0 rd.dm=0
    initrd (loop)/isolinux/initrd0.img
}

$ sudo update-grub

위의 메뉴엔트리에서 주의해야 할 부분이 isoname과 isolabel이 다르다는 점이다. 이것 땜에 좀 많이 헤매야 했다.

설치 과정

페도라 설치 UI도 직관적이어서 우분투와 마찬가지로 설치시에 큰 어려움이 없다. 한글로도 설치가 잘된다. 한가지 우분투와 다른 점은 사용자 계정은 물론이고 root 계정도 설정해야 한다는 것이다. 우분투에 적응이 되어 있어서 root 계정을 사용하는 것은 부담스럽다. 패스워드 두개를 외워야 한다는 거... 그렇다고 패스워드를 한개로 통일하면 root 계정을 쓸 이유가 없다.

페도라 설치시 파티션을 자동 설정으로 두면 /boot 파티션을 ext4 파일시스템으로 만들고, 나머지 공간은 LVM으로 구성한다. 서버 사용자라면 문제될 게 없지만 Desktop 환경에서는 Logical Volume을 사용하는 것보다 물리적인 파티션을 사용하는 것이 안전하다는 고정관념이 머리 속에 남아 있다.

설치 후 최초 부팅했을 때 사용자 환경 설정을 한다는 점도 다른 점이다. 여기서 한글(Hangul) 입력기를 선택하면 ibus-hangul을 바로 사용할 수 있다. 초보자들에게는 이런 방법이 더 나을 수도 있겠다 싶다.

root 계정 안쓰기

사용자 계정이 하나 있으니까 우분투 처럼 root 계정을 안쓰고 sudo 권한을 주기로 했다. sudo 권한을 주려면 당연히 root 계정을 사용해야 한다.

$ su - root

우선 아래와 같이 사용자 계정에 wheel 그룹을 추가해 준다. Redhat 계열 리눅스에서 wheel 그룹은 /etc/sudoers 파일에 root 권한을 갖도록 설정되어 있다.

$ usermod -aG wheel aaa

이제 root 암호에 lock을 걸어 버림으로써 root 계정으로 직접 또는 ssh 등으로 login할 수 없게 된다.

$ passwd -l root

나중에 root 계정을 다시 사용하고자 한다면 사용자 계정에서 아래와 같이 해주면 된다.

$ sudo passwd -u root

사용자 계정에서 sudo를 사용하기 위해서는 사용자 계정으로 재로그인 해주면 된다.


DNF 패키지 관리자

DNF는 Dandified Yum(멋쟁이 yum?)이란다. 좀 기억하기는 어렵다. yum을 버리는 이유는 패키지 의존성 문제를 해결하기 어렵고 yum에 대해 문서화가 잘 안되어 있어서 API가 혼란스럽기 때문이란다. 사용법 자체는 yum과 거의 비슷하기 때문에 큰 문제는 없으나(?)... 그래도 배우는데 시간이 걸릴 듯...

일단, WIFI 문제 때문에 repo를 추가해야 했는데 DNF 사용법을 몰라서 한참 헤맸다. yum과 좀 많이 다르다... 아래와 같이 추가하면, 결국은 /etc/yum.repos.d에 아래의 free와 nonfree repo 두 개가 추가된다.

$ sudo dnf config-manager --nogpgcheck --add-repo http://download1.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm
$ sudo dnf config-manager --nogpgcheck --add-repo http://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -E %fedora).noarch.rpm

그런데, 아직 Fedora 22 드라이버가 올라와 있지 않아서 dnf로 kmod-wl 패키지를 다운로드할 수 없었다.

패키지 의존성 문제를 해결했을지는 모르지만, 패키지 자체의 문제가 있어 보인다. 위의 repo가 아직 Update 되지 않은 것은 제외하고도... gcc를 설치하는데 커널 소스를 debug 버전으로 설치하더라. VirtualBox guest addition을 컴파일하는데 오류가 나서 알고 봤더니 kernel debug 버전 때문에 생긴 문제였다는... dnf로 이거 지우고  kernel-devel을 다시 설치했더니 잘 된다.

또, 한가지 문제는 dnf는 command-line이고 이와는 별개로 패키지 설치를 위해 Gnome Shell에서 우분투 소프트웨어 센터와 비슷한 Software란 놈을 사용할 수 있는데 패키지 설치 history가 통합 관리되지 않는다는 점이다. dnf로 설치한 history만 알 수 있다. 우분투는 apt-get으로 설치하든 우분투 소프트웨어 센터를 사용하든 설치된 패키지에 대한 history를 우분투 소프트웨어에서 확인할 수 있다. 물론, dpkg나 deb으로 설치한 소프트웨어 history는 우분투에서도 안보이지만 이 들이 표준 방식은 아니니까...

이 Software란 놈이 또 한가지 웃기는 점이 있는데, 페도라 패키지를 Update하면 설치하기 전에 페도라를 한번 부팅하고나서 Update 설치 후에 또 한번 페도라를 부팅시킨다. 아니, kernel 4.0에서는 심지어 kernel update조차 컴퓨터를 부팅시키지 않으려고 하는데 이 무슨 망나니짓임? 한번도 아니고 두번씩이나 컴퓨터를 부팅시키다니... 아, 물론 dnf를 사용하면 아예 부팅하지 않는다.

$ sudo dnf upgrade

물론, 리눅스에서 부팅하지 않는다고 방금 update한 패키지를 바로 사용할 수 있다는 것은 아니다. 하지만 대부분의 경우에는 재로그인 하는 것만으로도 update한 패키지를 바로 사용할 수 있다.

Gnome 3.16

Gnome 3.16에서 눈에 띄는 두 가지 달라진 점이 있었다. 하나는 Notification이 달력과 통합되어 Top bar의 중앙에 날짜 옆에 점으로 표시된다는 것이다. 또, 한가지는 Window Title Bar가 매우 단순해 졌다는 것이다. 가령, gedit를 예로 들면, 수직으로 Window Title Bar, Menu Bar, Tool Bar의 세줄이 필요했던 것을 한 줄에 몰아 넣었다. 구글 chrome과 비슷하다. 세 줄이 한 줄로 줄었으니 화면의 수직 공간을 매우 절약하게 된다. 물론, Gnome-shell에서 딸려오는 애플리케이션에 한해서만 그렇다는 얘기다.

사실, 내가 우분투의 Unity Desktop 환경을 고집해 온 가장 큰 이유 중의 하나가 수직 공간에서 소위 LIM(Locally Integrated Menu)이 Window Title Bar와 통합되어서 2줄이 1줄이 되기 때문이었는데 Gnome 3.16에서는 무려 3줄이 1줄로 된다는 것이 매우 기쁜 일이 아닐 수 없다. 다만, Menu와 Tool Bar가 통합됨으로 인해 애플리케이션에서 특정 기능을 사용하고자 할 때는 불편함이 생긴다.

Unity Desktop의 Top panel을 숨길 수 없는데 반해서 Gnome Shell은 Hide-Topbar shell extension을 설치하면 Top Bar autohide가 되기 때문에 수직 공간을 추가로 절약할 수 있다. 이것은 엣 버전에서도 가능했던 일이다.

그러나, 아쉬운 점은 통합된 Window Title Bar의 수직 폭이 좀 넓어 졌다는 것이다. ~/.config/gtk-3.0/gtk.css에서 줄일 수 있다는데 안 줄어 들더라... 덩달아서 gedit의 경우 파일을 여러개 열면 Tab이 생기는데 Tab의 수직 폭도 넓어 졌다는... 쩝... 그래서, 결과적으로 Unity Desktop 환경과 비교하면 뭐 별로 수직 공간이 절약된 느낌이 들지는 않는다. 도대체 어쩌자는 거임...? ㅠ.ㅠ

Kernel 4.0 live patching

아직 페도라 업데이트 중에 커널이 포함된 적이 없어서 아직 테스트를 해볼 수 없었다. 나중에 기회가 되면... Fedora 22 출시된지 얼마 되지도 않았는데 무리한 요구를 할 수는...

Fedora 22에 대한 전반적인 소감

우분투 사용자들에게 페도라를 권하고 싶지는 않다. 특히, 리눅스 초보자들에게는 우분투를 권하고 싶다. 기본적인 패키지 관리 문제도 그렇고, H/W 드라이버 문제도 그렇고 우분투가 훨씬 사용자 친화적인 Desktop 환경이라고 볼 수 있다.

다만, 앞서 얘기했듯이 최신 Open Source 소프트웨어들을 빨리 접해 보고 싶은 이들에게는 당연히 우분투 보다 Fedora를 권하고 싶다.

fedora 22에서의 한글 입력기 설정은 우분투 14.10이후의 ibus-hangul 설정 방법과 근본적으로 동일하다고 보면 된다.

2015/05/30

리눅스 배포판 선택에 대한 잡담


리눅스 배포판이 문제?

리눅스 사용자들이 어떤 배포판을 선택할지 고민하는 경우가 많기 때문에 약간의 고민을 덜어 주고 싶다. 리눅스 관련 커뮤니티에 올라온 질문 들 중에 이런 내용들을 보면 좀 답답하게 느낄 때가 있어서이다. "우분투에서는 WIFI가 잘 되는데 페도라에서는 안된다." "페도라에서는 한글입력이 잘 되는데 우분투에서는 안된다." 또는, "Gnome Shell에서는 한글입력이 잘 되는데 KDE에서는 안된다." 더구나 그 결론이 잘 되는 배포판이나 Dektop으로 갈아타야겠다고 할 때가 많다는 것이다.

기본적으로 동일한 PC 환경에서 특정 배포판 또는 Desktop 환경에서는 잘 되는데 다른 배포판이나 Desktop 환경에서 안되는 이유는 패키지 설치 방법이나 설정 방법이 조금씩 다르기 때문이다. 그러니까, 단지 이런 류의 문제들 때문에 배포판이나 Desktop을 바꾸는 것은 시간 낭비라는 것을 말해 주고 싶다.

나의 경우에, 다른 배포판이나 Desktop을 설치하는 주된 이유는 새로운 기능을 빨리 접해 보고자 할 때이다. 물론, 이외에도 PC 사양, 시스템 안정성이나 편리성, 시스템 보안, 특별한 리눅스 사용 목적, Desktop에 대한 Design 등도 배포판이나 Desktop 선택에 대한 주요 이유가 된다.

리눅스 배포판 들...

우선, DistroWatch에서 배포판에 대한 Page 방문 통계 순위를 제공하는데, 어느 정도 신뢰할 수 있기 때문에 여기를 참고하면 괜찮은 배포판을 선택할 수 있다. Top 5까지는 국내 사용자들도 많기 때문에 문제가 생겼을 때 도움을 얻을 수 있다. 리눅스 배포판들은 역사적으로 특정 시점에 인기 있는 배포판을 기반으로 이를 개선해서 새로운 배포판이 탄생한 경우가 많기 때문에 족보를 갖고 있다고 볼 수 있다. 주요 배포판 중에 Debian이나 Redhat, OpenSuse, Slackware 등은 고조 할배 뻘이 된다. Ubuntu는 Debian에서 분기했는데 Mint나 elementary OS 등 자식들을 많이 두고 있다. Fedora는 CentOS와 함께 Redhat에서 갈라져 나왔다. 같은 할배 밑의 자손들은 리눅스 명령이 거의 비슷하고 대체로 binary 호환성도 유지된다. 할배가 다르면 리눅스 기본 명령은 대부분의 Unix 계열 명령과 거의 같지만, 명령 자체가 다른 경우가 많고 binary 호환성도 보장 받지 못한다. 또한, 기본 명령조차도 배포판에 따라 실행 결과가 조금씩 다를 수도 있다.

그리고, 할배가 낫냐 손자가 낫냐 따지는 것도 큰 의미는 없다. 할배를 개선해서 손자가 탄생했지만, 할배도 계속 Upgrade하면서 새로운 것들을 받아 들이기 때문이다. 더구나, 기본 패키지들은 할배의 저장소에서 가져 오는 경우가 많기 때문에 손자의 S/W 버전이 할배 보다 낮은 경우도 많다. 대부분의 리눅스 배포판들은 부모 배포판이 버전 업되고 나서야 자식 배포판이 버전 업된다.

리눅스 Desktop 환경 들...

리눅스 배포판 내에서도 Desktop(GUI) 환경에 따라서 또 사용자가 나뉜다. Desktop 환경에 따라서 리눅스에 대한 Look & Feel이 달라질 수 있고, GUI 애플리케이션도 조금씩 다르다. Ubuntu만 해도 기본 Desktop인 Unity외에 Gnome Shell, KDE(Kubuntu), XFCE(Xubuntu), LXDE(Lubuntu), Mate, Cinnamon, Panthon... 등등을 사용할 수 있다. Desktop 환경도 대부분의 경우에는 다른 리눅스 배포판에서도 사용할 수 있다. 예를 들어, Gnome Shell은 페도라의 기본 Desktop 환경이고, KDE나 Mate 등을 페도라에서도 사용할 수 있다. 더구나, 한 배포판 내에서 여러가지 Desktop 환경을 동시에 설치해서 사용할 수 있다.

다만, 특정 Desktop 환경에서 다른 Desktop 환경의 애플리케이션을 사용할 목적이라면 굳이 여러개의 Desktop을 설치할 필요도 없다. 해당 애플리케이션의 패키지를 그냥 설치해서 사용하면 된다. 가령, Gnome Shell에서 KDE 애플리케인션인 Okular만 설치해서 사용할 수 있다. 물론, Gnome은 GTK 라이브러리 기반이고 KDE는 Qt 라이브러리 기반이기 때문에 Okular를 설치하면 필요한 Qt 라이브러리 들이 같이 설치된다.

도찐개찐

하지만, 궁극적으로 내가 하고 싶은 얘기는 리눅스 배포판 들은 개콘 코너에서 얘기하듯이 도찐개찐이라는 것이다. 할배 배포판들까지 포함해서 하는 얘기다. 가령, 우분투에서 Gnome Shell을 쓰는 것과 페도라에서 Gnome Shell을 쓰는 것은 겉보기에 아무런 차이가 없다. GUI 애플리케이션들은 Desktop 환경이 동일하면 리눅스 배포판과 상관없이 거의 동일하다. 다만, 리눅스 배포판의 차이에 따른 명령어들은 다르다. 가장 차이가 많이 나는 부분은 Package 관련 명령들인데 이것을 빼면 대부분의 명령이나 애플리케이션 들은 거의 동일하다.

근본적으로 리눅스 kernel이나 H/W 드라이버 들은 똑같다. 특정 배포판에서 H/W가 동작하는데 다른 배포판에서 동작하지 않을 확률은 거의 0에 가깝다. 기본 S/W나 애플리케이션들도 Open Source이기 때문에 대부분의 경우 특정 배포판에서만 안되는 일은 거의 없다고 봐도 무방하다.

리눅스 배포판/Desktop 추천

뭐, 리눅스 커뮤니티에 기여하기 위해 일부러 리눅스 배포판이나 Desktop 환경을 바꾸는 사람들에게는 감사해야겠지만, 단지 어떤 것이 예뻐 보인다는 이유만으로 바꾸는 사람들에게는 맘에 드는 한가지를 선택해서 정착하라는 것이 결론이다.

가령, 우분투 자손인 elementary OS는 무겁지도 가볍지도 않은 중간 쯤의 Desktop 환경인 Pantheon Desktop 환경을 사용하는데 보기는 좋으나 여러가지 불편함을 감수해야 한다. 그래서, 일반 사용자에게 우분투는 가장 무난한 배포판이고 Desktop 환경은 개인적인 선호도가 있기 마련이니까 Unity, Gnome Shell, KDE 셋 중에 하나를 추천한다. Netbook과 같이 PC 사양이 너무 낮은 경우(Mobile CPU, RAM 2GB 미만)에 한해서 리눅스 GUI를 사용하고자 할 경우에는 어쩔수 없이 Mate, LXDE/LXQt, XFCE 등을 권한다.

리눅스 Desktop 환경의 성능은 CPU가 특별히 매우 낮은 사양이 아니라면 RAM 용량에 의존하는데, 그래봤자 가장 무거운 Unity와 가벼운 편인 Mate하고 비교하면 최대 500MB 정도 밖에 차이나지 않는다. RAM이 4GB이상이면 Virtualbox로 다른 guest OS를 설치해도 큰 문제는 없다.

2015/05/24

Ubuntu 15.04 systemd 부팅 시간 줄이기


systemd 매번 부팅시마다 fsck 검사하는 문제

우분투 15.04부터 본격적으로 systemd를 채택했으니 여기에 적응할 필요가 생겼다. 기본적으로 매번 부팅할 때마다 fsck가 파티션 별로 file system check를 하다보니 10초 정도를 허비하고 있다는 것을 알았기 때문이다. Ctrl-C로 취소할 수 있다고 메시지가 뜨지만 실제로 Ctrl-C도 동작하지 않는다. 이 두 가지 문제 중에서 첫번째만 해결되면 Ctrl-C가 동작하지 않아도 큰 문제는 없다.

systemd에서는 부팅 후 터미널에서 아래의 명령으로 부팅 시 소요 시간과 서비스(systemd unit service)별 병목 구간을 알 수 있다.

$ systemd-analyze
$ systemd-analyze blame
$ systemd-analyze critical-chain

예전에 fsck 주기를 mount 횟수나 일정 시간 간격으로 설정할 수 있었던 기억이나서 tune2fs를 가지고 별짓을 다 해 보아도 부팅시 fsck가 파일시스템 검사하는 것을 막을 방법이 없었다. 구글링으로 찾은 방법은 /etc/fstab 파일에서 <Pass> 파라미터를 0으로 바꿔주면 해당 파티션은 fsck 검사를 하지 않는다는 것이다. 모든 파티션에 대해 파라미터를 0으로 수정하고 재부팅하니, 과연 10초 정도 부팅속도가 빨라졌다. 뭐 이 방법도 나쁜 방법은 아니지만, fsck를 고생해서 쓰라고 우분투에 넣었는데 안쓰는 것도 좀 미안한 생각도 들고, 왠지 가끔씩은 돌려야 할 것 같아서 더 좋은 방법을 찾아 보기로 했다.

e2fsck time-stamp 문제

우분투 관련 사이트에는 systemd 사용역사가 짧아서인지 문제점을 지적한 글을 찾을 수 없다. 역시, systemd를 처음 채택한 Fedora 관련 사이트에서 이 두가지 문제에 대한 글들을 찾을 수 있었다. fsck 버그란 얘기도 있고 fsck time-stamp 때문이란 얘기도 있다. 실제로 아래의 명령으로 fsck time-stamp 문제가 발생하는 것을 확인할 수 있었다.

$ journalctl | grep -i fsck
May 23 17:20:10 localhost.localdomain systemd-fsck[278]: ROOTFS: Superblock last write time is in the future.
May 23 17:20:10 localhost.localdomain systemd-fsck[278]: (by less than a day, probably due to the hardware clock being incorrectly set). FIXED.
또, 아래 명령으로 리눅스 ext 파티션의 mount와 최종 fsck 시간을 확인할 수 있는데 UTC time으로 로그가 찍힌다.

$ sudo tune2fs -l /dev/sda8

가만히 생각해 보니, Windows와 Ubuntu의 시간을 맞추기 위해 /etc/default/rcS 파일에서 UTC=yes 설정을 UTC=no로 바꾸었다는 것을 깨닫게 됐다. 이 설정은 컴퓨터 내장 시계의 시간 기준이 UTC인지 local time인지를 부팅시에 알려 준다. 추정컨대, H/W clock이 local time으로 설정되어 있어서 fsck 검사시에 local time으로 최종 시간을 파일시스템에 저장했는데 다시 fsck 검사할 때는 이것이 UTC time이라고 생각하기 때문에 발생하는 문제인 듯 싶다. 즉, 우리나라 local time인 KST = GMT+09로 UTC 시간 보다 9시간이 빠르다. 참고로, 시간 설정에 대한 정보는 아래의 명령으로 확인할 수 있다.

$ timedatectl status
$ sudo hwclock --show

문제 해결?

아무튼 /etc/default/rcS 파일을 원래대로 UTC=yes로 저장하고 재부팅했더니 파일시스템 검사 시간이 줄어 들었다. 검사 시간이 줄어드는 정도로는 안되고 아예 검사를 하지 말아야 한다. journalctl 명령으로 확인해 보니, EFI System Partition(ESP)에 대해서만 fsck가 파일시스템 검사를 했음을 알 수 있었다. ESP는 vfat 파일시스템이므로 fsck 검사시간 정보 등을 저장할 수 없다. 예외적으로 이 놈에 대해서만 /etc/fstab의 <Pass> 파라미터를 0으로 설정하기로 하였다. 이 후로 몇번 재부팅해봤는데 더이상 fsck가 돌지 않아서 부팅시간이 10초 정도 빨라졌다.

vfat 빼고는 생기지도 않았을 문제를 해결했다니 느낌이 좀 이상하네...

systemd 부팅 시간 쬐금 더 줄이기

systemd에서는 서비스들을 unit 단위로 관리한다. unit 간에 의존성이 있을 수도 있다. 일단 아래의 명령으로 현재 서비스 unit과 상태를 확인할 수 있다. 상태는 enabled, static, disabled, masked의 4가지가 있을 수 있는데, static은 다른 unit과 의존 관계가 있다고 이해하면 될 듯하다. masked는 disable 시킨건 아니지만 의존 관계를 유지하면서 해당 unit만 disable 시키는 방법인 듯하다. 물론, 부팅 후 특정 서비스 unit을 stop하거나 start 할 수도 있다.

$ systemctl list-units --type service
$ systemctl list-unit-files --type service

그리고, systemd 서비스 unit을 부팅시에 동작하지 않도록 하거나, 다시 동작하도록 하려면 아래의 명령을 사용하면 된다.

$ sudo systemctl disable <unit 명>
$ sudo systemctl enable <unit 명>

앞서 systemd-analyze blame 명령에서 서비스 unit 별로 실행시간 profile을 알 수 있는데 시간이 오래 걸리는 놈들 중 불필요한 서비스 unit을 disable 시키면 된다. 아래 두 놈을 시범삼아 제거해 보았다. 참고로, fsck의 경우도 systemd-fsck@.service를 disable 시킬 수도 있지만 다른 unit와 의존관계가 있었고 아래 두 놈은 의존관계가 없어 보였다.

$ sudo systemctl disable ModemManager.service
$ sudo systemctl disable bluetooth.service

결론

위의 두 놈을 제거후 재부팅했더니 5초 정도 부팅시간이 빨라졌다. fsck까지 포함해서 15초를 절약하게 됐다. 그래서 총 부팅시간이 35초에서 20초 정도로 줄었다는 것이 결론이다. 뭔가 허무한 느낌... 더구나 애초에 /etc/default/rcS 파일을 건드리지 않았으면 fsck에 대한 10초도 빨라진게 아니라는... ㅠ.ㅠ

참고 사항

위에서 우분투 H/W 시간 기준을 UTC로 바꾸고 Windows로 부팅하면 Windows에서는 그 시간을 local time이라고 해석하기 때문에 시간이 UTC time으로 바뀌어 9시간 느린 시간이 표시될 수 있다. 특히, NTP time 서버와 동기화 되지 않을 때 이 문제가 생기는데 Windows Scheduler에서 NTP 서버 동기화 작업을 걸어 주거나, Windows에서도 H/W 시계의 시간 기준이 UTC라고 알려 주는 방법도 있단다. Mac OS X의 경우에는 Unix 계열이므로 리눅스와 마찬가지로 timezone으로 시간을 설정하므로 시간 불일치 문제는 발생하지 않는다.

2015/05/07

Syntax Highlighter 구 버전으로 회귀


구관이 명관이라는 말이 실감난다. 최신 버전의 Syntax Highlighter를 이 블로그에 적용했었는데 구 버전으로 회귀해야했다. 신 버전은 테마를 사용할 수 있어 깔끔하고, 원저자의 사이트 링크들만 블로그 Template에 복사하면 되었기에 구글 블로그에 적용하기가 매우 편리하다.

그런데, 어제 저녁에 갑자기 내 블로그에 접속이 안되는 일이 발생했다. www.blogger.com에는 접속이 되는데 내 블로그에는 접속이 안되는 황당한 상황이었는데 Firefox가 원인을 알려 주었다. 내 블로그에 접속하려면 Syntax Highlighter 사이트를 거쳐와야 했는데 거기에 접속이 안되니까 내 블로그에도 접속이 안되는 상황이 발생한 것이다. 해킹을 당한건지 서버가 망가진건지 알 수 없지만 지금도 해당 사이트로는 접속이 안된다.

내 발등에 떨어진 불을 끄기 위해 신버전의 Syntax Highlighter를 걷어내야 했다. 그리고 구버전을 설치했다. 구 버전에서도 링크를 병행해서 사용해야 하지만 syntaxhighlighter.googlecode.com 링크를 사용하기 때문에 상대적으로 안전하다. 문제는 구버전과 신버전 tag가 달라서 예전에 올린 글들을 일일이 수정해야 하는데 귀찮아서 모두 수정할수 있을지 장담하기 어렵다.

요즘 알게 모르게 Cloud 환경을 많이 사용하고 있는데 구글 같은 대형 사이트가 아니면 언제든지 유사한 일을 당할 수가 있다. 뭐, 구글같은 사이트도 정책이 바뀔 수도 있으니 아무튼 미래에도 Cloud 환경이 안전하다고 맹신하면 안될 것이다. 전에 iPhone을 애들이 갖고 놀다가 비밀번호를 바꿨는데 기억을 못하는 바람에 iOS부터 새로 설치해야 했던 적이 있는데 다행히 iCloud를 사용하고 있어서 중요한 데이터가 거의 완벽히 복구된 적이 있었다. 그런 면에서 Cloud 환경이 편리한 것도 사실이다. 하지만, Syntax Highlighter 문제와 같이 Cloud 환경의 위험성에 대해서도 경각심을 가져야 할 것이다.

구 버전의 Syntax Highlighter 설치 방법은 stackoverflow.com에 올라와 있는데 Backup 차원에서 이 글에 다시 남긴다.

1. 먼저, blogger template을 백업

2. http://syntaxhighlighter.googlecode.com/svn/trunk/Styles/SyntaxHighlighter.css의 파일 내용을 </b:skin> tag 앞에 복사

3. 아래 내용을 </head> tag 앞에 복사: 필요한 brush 파일만 선택
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shCore.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushCpp.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushCSharp.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushCss.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushDelphi.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushJava.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushJScript.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushPhp.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushPython.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushRuby.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushSql.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushVb.js' type='text/javascript'></script>
<script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushXml.js' type='text/javascript'></script>
4. 아래 내용을 </body> tag 앞에 복사
<script language='javascript'>
dp.SyntaxHighlighter.BloggerMode();
dp.SyntaxHighlighter.HighlightAll('code');
</script>
5. blogger template 저장

6. 사용 방법은 아래와 같이 <pre name="code" class=cpp></pre> tag 사용
<pre name="code" class="cpp">
int x = 0, y = 10;
</pre> 
7. 사용 가능한 Brush class: cpp, csharp, css, delphi, java, js, php, python, ruby, sql, vb, xml

2015/05/06

Qt 5.4 fcitx immodule Build 및 한글 사용


이전 글에서 우분투 15.04 Unity Desktop 환경에서 한글 입력기로 fcitx를 추전했는데, 막상 Qt 5.4의 Qt creator에서는 한영키가 동작하지 않아 황당했다. 당연히, 이 Qt creator로 build한 Qt 5.4 애플리케이션에서도 한영키가 동작할리 없다. 이전 글에서 테스트한 Qt 앱은 Qt 5.3에서 build 했던것 같다. 한마디로 우분투 패키지로 다운 받은 fcitx는 최신 버전의 Qt 5.4를 지원하지 않는 것 같다. 뭔가 달라진 듯...

구글링하니까 마침 일본 블로그에 fcitx build하는 방법이 올라와 있어서 다시 build 한 후 Qt5 immodule를 복사해 넣었더니 모든 Qt 애플리케이션에서 한글입력이 잘 된다. 다만, 그 블로그 내용을 그대로 따라하니까 안되더라... 그래서 다시 정리한다.

Qt 5.4에서 fcitx Qt5 immodule build

$ sudo apt-get install git cmake

$ git clone https://github.com/fcitx/fcitx-qt5.git
$ cd fcitx-qt5
$ git checkout 0.1.3

build 하기 전에 Qt 5.4가 설치된 홈 폴더를 미리 알아 두어야 한다. 나의 PC에는 /opt/OpenSrc/Qt에 설치하였다.

$ cmake . -DCMAKE_PREFIX_PATH=/opt/OpenSrc/Qt/5.4/gcc_64
$ make

기존 fcitx 패키지로 설치된 Qt5 immodule 대체 설치

기존의 우분투 fcitx 패키지에 딸려온 Qt5 immodule을 대체해버리는 것이 가장 좋은 설치 방법이다. 안전을 위해 원래 파일은 org.libfcitxplatforminputcontextplugin.so로 백업했다.

$ sudo mv /usr/lib/x86_64-linux-gnu/qt5/plugins/platforminputcontexts/libfcitxplatforminputcontextplugin.so /usr/lib/x86_64-linux-gnu/qt5/plugins/platforminputcontexts/org.libfcitxplatforminputcontextplugin.so

$ sudo cp ./src/libfcitxplatforminputcontextplugin.so /usr/lib/x86_64-linux-gnu/qt5/plugins/platforminputcontexts/

또 한가지 대체해야 할 파일이 있다는 것을 나중에 알았다. Qt5 immodule이 사용하는 runtime library 파일 하나가 같이 build 되었다. 이 놈까지 버전이 일치해야 한다.

$ sudo mv /usr/lib/x86_64-linux-gnu/libfcitx-qt.so.0.1 /usr/lib/x86_64-linux-gnu/org.libfcitx-qt.so.0.1

$ sudo cp ./fcitx-qt5/libfcitx-qt5.so.0.1 /usr/lib/x86_64-linux-gnu/libfcitx-qt.so.0.1

참고 사항

참조한 일본 블로그에는 환경 변수 설정 같은 것들이 있다. 그렇지만 .bashrc에 입력기 환경변수를 넣으면 X-Window의 실행 순서 때문에 환경변수가 제대로 동작하지 않을 수도 있다. 편하고도 안전한 방법은 먼저 fcitx 패키지를 설치하는 것이다. 이 글은 fcitx 패키지가 먼저 설치된 것을 전제로 했다.

일본 블로그에서 설명하듯이 기존 파일들을 대체하지 않고도 새로 build한 Qt5 immodule을 사용할 수도 있는데 runtime library가 두 개라 환경 설정을 제대로 해주어야 한다(기존 패키지와의 충돌때문에 설정이 다소 복잡하므로 세부 설명은 안한다). 다만, Qt5 immodule을 복사해야 할 폴더는 /opt/OpenSrc/Qt/5.4/gcc_64/plugins/platforminputcontexts가 아니고, /opt/OpenSrc/Qt/Tools/QtCreator/bin/plugins/platforminputcontexts이더라. 뭐, 두 곳에 다 복사해도 상관은 없다.

2015/05/05

우분투 15.04 fcitx-hangul 설치 및 설정


우분투 15.04에서 기본 입력기인 ibus가 큰 문제가 있는 건 아니지만, 최근에 Qt5를 배우면서 Qt5 입력기 모듈을 제공하는 fcitx를 설치해 보기로 했다. ibus나 uim 입력기는 Qt5 애플리케이션에서 한글 입력시 띄어쓰기 등의 문제가 발생한다. ibus의 경우 이 문제에 대해 버그 리포팅 한지 1년이 다 돼가는데 Qt5.5 이후에나 사용할 수 있을 듯 하다.

참고로, ibus나 fcitx 주 개발자는 중국인이고 uim은 일본인이다. ibus-hangul과 nabi 개발자는 한국 사람인데 그가 만든 libhangul을 fcitx-hangul 입력기에서 사용하고 있다. 그래서 그런지 몰라도 ibus-hangul에서 발생하는 마지막 입력글자가 마우스 이동시 따라 다니는 문제는 fcitx-hangul에서도 발생한다. uim-byeoru를 만든이도 또 다른 한국인인듯 하다. 한글 입력기의 문제는 한국 개발자들이 주개발자가 아니고 한글 입력기 모듈만을 만든는데서 비롯되는 것인지도 모른다. 워낙에 개발자 저변이 열악하다 보니 한번 만들면 유지보수나 사용자 지원이 잘 이루어지지 않고 있는 것이 현실이다.

fcitx를 설치 후 사용해 본 바로는 현재까지의 입력기들 중에선 우분투 유니티 데스크탑 환경에서 가장 좋은 한글입력기라고 말하고 싶다. 기본적으로 유니티 상단 패널에서 한영 전환 상태를 구분할 수 있고, 한자 입력은 물론이고 virtual keyboard를 이용해서 일본어나 특수문자 입력도 가능하다. Qt5 입력 모듈이 기본 제공되고 있어 Qt5 애플리케이션에서도 한글입력이 잘 된다.


fcitx 설치

아래와 같이 fcitx-hangul 패키지만 설치하면 필요한 패키지들이 모두 설치된다.

$ sudo apt-get install fcitx-hangul

패키지 설치 후 기본 입력기인 ibus대신 아래 화면과 같이 [System Settings] > [Language Support]에서 [Keyboard input method system:]의 [fcitx]를 선택한 후, 다시 로그인해야 한다.


한글 키보드 추가 및 한영키 설정

재로그인 후, fcitx 설정 프로그램을 실행해야 한다. 유니티 패널 상단의 키보드를 클릭하여 Configure를 선택하거나, <Super> Key를 눌러서 유니티 대쉬에서 fcitx를 검색해서 나오는 [fcitx Configuration] 아이콘을 선택해서 기동해도 되고, 터미널에서 아래 명령으로 실행해도 된다.

$ fcitx-config-gtk3

먼저, 아래 화면과 같이 [Input Method] 탭 하단 왼쪽의 [+] 버튼을 눌러 Hangul 키보드를 검색한 후 선택하여 추가해 준다. 참고로, 내 경우엔 우분투 기본언어를 영어로 사용하고 있어서, 한글을 기본 언어로 사용하는 경우에는 반대로 Keyboard-English(US)를 추가해야 할지도 모르겠다. 그리고, 두개의 키보드가 추가된 상태에서 위에 있는 키보드가 기본 키보드가 된다. 즉, Hanul 키보드가 위에 있도록 순서를 조정하면 터미널 등의 애플리케이션 실행 후 한글 입력 상태가 된다.


참고로, 이렇게 추가된 키보드는 [System Settings] > [Text Entry]에서도 확인할 수 있는데 한글 키보드는 Hangul (Fcitx)로 표시된다.

이제, 한영전환키로 한영키만 설정해 주면 된다. 아래 화면과 같이 [Global Config] 탭에서 [Trigger Input Method]에 [Ctrl+Space]와 [Empty]로 표시되어 있는 버튼을 각각 눌러서 [한/영]키와 [Shift+Space]키로 바꿔주면 된다.


추가 설정

위의 과정까지만 해 주어도 fcitx를 입력기로 쓰는데 큰 지장은 없는데, 아래 화면과 같이 한글로 전환시 [Hangul]이라고 표시되는 작은 창이 뜨는게 좀 귀찮아서 없애기로 하였다.


위의 화면에 없애는 방법도 같이 보여주고 있는데, gedit로 ~/.config/fcitx/config 파일을 열어서 "ShowInputWindowAfterTriggering=False" 부분을 설정해서 저장한 후,

$ gedit ~/.config/fcitx/config

아래 명령으로 fcitx를 재기동 해주면 된다.

$ fcitx -r

Virtual Keyboard 사용

맨 위의 스크린 샷에 보이는 virtual keyboad를 사용하려면 유니티 상단 패널의 키보드나 태극문양 아이콘을 클릭해서 [Toggle Virtual Keyboard]를 선택하면 키보드가 나타나고, 한번더 선택하면 사라진다. 마우스로 Virtual Keyboard의 [Latin] 부분을 선택하면 번갈아 가면서 일본어 등 다른 키보드들을 선택할 수 있다. 또한, 마우스로 특수문자를 입력해도 되고 해당 키보드가 선택된 상태에서 실제 키보드를 입력해도 해당 키의 특수문자가 입력된다.

fcitx 자잘한 문제들

앞서 언급했던 ibus-hangul과 동일한 한글 마지막 입력글자가 마우스 따라다니는 문제 외에, 우분투 VirtualBox 게스트에서 영문 모드 상태의 유니티 Dash에서 한영키가 동작하지 않아 한글이 입력되지 않는 문제가 있었다. 우분투 호스트에서는 그런 문제는 안생기고 있다. 또, 한가지는 ibus-hangul에서도 발생하는 문제인데, 영문모드 상태에서 구글 chrome 브라우저를 실행하자마자 주소창에서 한영키를 누를 경우 한영전환이 안되는 문제가 있다. 주소창이 아닌 검색창에서 한영키를 누르면 한영전환이 잘 된다.

추가적으로, 다시 ibus를 사용하고자 할 경우 [System Settings] > [Language Support]에서  [fcitx] 대신 [ibus]를 선택하고 재로그인 해 주면 되는데, 한영키를 사용하려면 Hangul (ibus) 키보드를 다시 추가해 주어야 한다. 이때 불필요한 fcitx 프로세스 하나가 같이 살아있는 문제도 있다.

2015/05/01

Qt5 Mouse Event 처리


Qt5도 배울 겸 재미삼아 마우스 이벤트 처리 프로그램을 만들어 본다. UI 프로그램을 거의 짜 본적이 없어서 그런지 마우스 이벤트 처리가 생각보다 복잡하다. 소시적부터 관심이 있었으면 Libre Office Impress 같은 것을 만들었을지도... 도형 들을 마우스로 선택하고 옮기고 크기를 조절하고 Widget 창 크기 조절시 창크기에 비례해서 도형 크기도 변해야 한다. 마우스 커서도 선택 모드, 드래그 모드, 리사이즈 모드에 따라 바꿔주고... 우분투의 Screenshot으로 캡춰했더니 마우스 커서는 모양이 안바뀌네...

그런데, Qt에서 사각형 Class인 QRect가 좀 웃긴다. QRect(x, y, width, height)로 생성할 수 있는데 x2 = x+width-1, y2 = y+height-1로 정의하고 있다. 가령, rect.x2()나 rect.y2()를 호출하면 각각 1pixel이 모자라게 된다. 그런데 놀라운 것은 painter.drawRect(rect)로 그리면 1pixel이 모자라지 않게 잘 그려준다. 별 문제가 없어 보이지만, 계산을 할때는 x2 = x+width, y2 = y+height로 계산해야 1pixel에 대해 제대로 고려가 된다. 또, 한가지 이로 인해 파생되는 문제는 rect.normalized()라는 함수가 width나 height가 음수일 때 양수로 사각형 좌표를 바꿔주는데 x와 x2를 swapping 해버림으로써 사각형 크기가 어긋나게 된다.

1pixel 차이 가지고 뭐 그리 쫀쫀하게 구냐고 할지도 모른다. 예전에 MS Powerpoint 발표자료 만들때 그룹 resize 같은 거 하면 pixel이 어긋나는 한 두놈이 꼭 생겨서 그거 맟추느라 고생했던 기억이 남아 있다. 왜냐하면 1pixel이라도 어긋나면 시청자에게 굉장히 허술하게 보이기 때문에... 최근 버전의 Powerpoint에서는 도형을 움직이거나 resize 하면 근처 도형에 정렬할 수 있도록 기능이 강화된 듯하다. 하지만 근본적인 문제가 해결된 것은 아니었다. 이 문제는, 표를 만들 때 무식한 방법으로 사각형 하나를 복제해서 한 줄을 만든 뒤 이 줄을 다시 복제해서 여러 줄을 만들고, 그룹 resize 후에 cell 들을 정렬시키고 나서 Powerpoint Window 화면을 resize해 보면, 금방 확인해 볼 수 있다. 표의 경계선 굵기가 일정하지 않게 되는 문제가 생긴다. Libre Office Impress에서는 resize시에도 정렬이 잘 되는 편이다.

그리고, Qt는 개발자에게 모든 필요한 것을 제공해 주려는 의도가 강해 보인다. 잡다하게 많은 Class 들이 뭐 썩먹을 수야 있지만 좀 난잡해 보인달까... 가령, int 버전의 QRect와 qreal(float) 버전의 QRectF와 같이 종류별로 int 버전과 qreal 버전을 구비하고 있다. 화면에서의 pixel들은 궁극적으로 int형이긴 하지만 resize나 reshaping 같은 것을 하기 위해서는 qreal 버전이 필요하기는 하다. 위의 pixel이 어긋나는 문제가 생기는 원인도 실수를 정수로 변환하면서 발생하는 rounding 오류 때문에 생긴다. 해결 방법은 가능한한 rounding 오류가 발생하지 않도록 해주면 된다. 가령, 특정 정수의 배수를 사용하여 나머지가 항상 0이 되도록 만들어 준다든지...


Mouse Press Event
void ChartWidget::mousePressEvent(QMouseEvent* event)
{
    m_firstPos = boundPos(event->pos());
    m_lastPos = m_firstPos;

    bool newPos = true;
    bool selectStat = false;
    bool modKey = event->modifiers().testFlag(Qt::ShiftModifier);
    bool itemSelected = m_selectedItems.size() ? true : false;
    QVariant info;

    if(itemSelected) {
        // if mod key pressed, deselect the selected item.
        if(modKey) {
            foreach(Drawable* drawable, m_selectedItems) {
                if(drawable->contains(m_firstPos, &info)) {
                    removeSelectedItem(drawable);
                    selectStat |= drawable->onDeselect();
                    newPos = false;
                    break;
                }
            }
        }
        else {
            // if reclick one of selected items, check new mouse event.
            foreach(Drawable* drawable, m_selectedItems) {
                if((m_resizeIndex = drawable->selectIndex(m_firstPos))) {
                    m_resizeMode = true;
                    m_mouseItem = drawable;
                    return;
                }
                if(drawable->contains(m_firstPos, &info)) {
                    m_dragMode = true;
                    return;
                }
            }
            // if new mouse position, deselect all the selected items.
            foreach(Drawable* drawable, m_selectedItems) {
                removeSelectedItem(drawable);
                selectStat |= drawable->onDeselect();
            }
        }
    }

    if(!itemSelected || newPos) {
        Drawable* clicked = drawableAt(m_firstPos, &info);
        // if new item is clicked select the item.
        if(clicked) {
            m_selectMode = false;
            m_dragMode = true;
            addSelectedItem(clicked);
            selectStat |= clicked->onSelect(event, modKey, info);
        }
        // if no item is selected check new select event.
        else m_selectMode = true;
    }

    if(selectStat) emit selectionChanged();
    if(!m_selectMode) reDraw();
    QWidget::mousePressEvent(event);
}
Mouse Move Event
void ChartWidget::mouseMoveEvent(QMouseEvent* event)
{
    m_lastPos = boundPos(event->pos());

    m_cursor = mcPointer;
    if(m_selectedItems.size()) {
        if(m_resizeMode) {
            m_cursor = (m_resizeIndex < 3) ? mcSizeLCross :
                       (m_resizeIndex < 5) ? mcSizeRCross :
                       (m_resizeIndex < 7) ? mcSizeVert :
                       mcSizeHoriz;
            m_selectRect = m_mouseItem->region();
            foreach(Drawable* drawable, m_selectedItems) drawable->onResize(m_resizeIndex);
            m_selectRect = m_mouseItem->region();
        }
        else if(m_dragMode) {
            m_cursor = mcDrag;
            foreach(Drawable* drawable, m_selectedItems) drawable->onMouseMove(event);
            m_firstPos = m_lastPos;
        }
        else {
            foreach(Drawable* drawable, m_selectedItems) {
                if((m_resizeIndex = drawable->selectIndex(m_lastPos))) {
                    m_cursor = (m_resizeIndex < 3) ? mcSizeLCross :
                               (m_resizeIndex < 5) ? mcSizeRCross :
                               (m_resizeIndex < 7) ? mcSizeVert :
                               mcSizeHoriz;
                    break;
                }
                if(drawable->contains(m_lastPos)) {
                    m_cursor = mcDrag;
                    break;
                }
            }
        }

    }

    reDraw();
    QWidget::mouseMoveEvent(event);
}
void Drawable::onMouseMove(QMouseEvent* event)
{
    Q_UNUSED(event)
    
    QRect rect = region();
    QPoint pos = rect.topLeft() + owner()->lastPos() - owner()->firstPos();
    setRegion(QRect(pos, rect.size()));
}
Mouse Release Event
void ChartWidget::mouseReleaseEvent(QMouseEvent* event)
{
    m_lastPos = boundPos(event->pos());
    //m_lastPos = adjustPosition(m_lastPos);

    bool modKey = event->modifiers().testFlag(Qt::ControlModifier);

    // if mouse left-click position changed.
    if(event->button()==Qt::LeftButton && (m_firstPos-m_lastPos).manhattanLength()>TOL_SELECT) {
        if(!modKey && m_selectedItems.size()) {
            foreach(Drawable* drawable, m_selectedItems) drawable->onMouseRelease(event);
        }
        else {
            bool selectStat = false;
            QVariant info = 0;
            QRect rect = QRect(m_firstPos, m_lastPos);
            foreach(Layer* layer, m_layers) {
                foreach(Drawable* drawable, layer->children()) {
                    // if non-selected items are in mouse dragged region, select new items.
                    if(rect.contains(drawable->region())) {
                        addSelectedItem(drawable);
                        selectStat |= drawable->onSelect(event, false, info);
                    }
                }
            }
            if(selectStat) emit selectionChanged();
        }
    }

    m_selectMode = false;
    m_dragMode = false;
    m_resizeMode = false;
    m_resizeIndex = 0;
    if(m_mouseItem) m_mouseItem = 0;
    reDraw();
    QWidget::mouseReleaseEvent(event);
}
void Drawable::onMouseRelease(QMouseEvent* event)
{
    Q_UNUSED(event)
    
    setRegion(positiveRect(m_rect));
    QVector2D ar = owner()->aspectRatio();
    m_rectOrigin.setWidth(m_rect.width()/ar.x());
    m_rectOrigin.setHeight(m_rect.height()/ar.y());
}
Widget Resize Event
void ChartWidget::resizeEvent(QResizeEvent* event)
{
    if(m_pixmap) delete m_pixmap;
    m_pixmap = new QPixmap(event->size());

    setViewportChanged();
    setViewport(rect());
    qreal arX = m_viewport.width() / m_viewportOrigin.width();
    qreal arY = m_viewport.height() / m_viewportOrigin.height();
    setAspectRatio(arX, arY);

    reDraw();
    setViewportChanged(false);
}
void Drawable::update()
{
    QVector2D ar = owner()->aspectRatio();
    qreal arX = ar.x();
    qreal arY = ar.y();
    if(owner()->viewportChanged()) {
        qreal x1 = arX * m_posOrigin.x();
        qreal y1 = arY * m_posOrigin.y();
        qreal x2 = x1 + arX * m_rectOrigin.width();
        qreal y2 = y1 + arY * m_rectOrigin.height();
        m_posCurrent = QPointF(x1, y1);
        // rounding errors are increased if you rsize chartwidget frequently.
        m_rect = QRect(RoundToMultiple(x1), RoundToMultiple(y1), 
                       RoundToMultiple(x2-x1), RoundToMultiple(y2-y1));
    }
    else {
        m_posCurrent = QPointF(m_rect.x(), m_rect.y());
        m_posOrigin = QPointF(m_posCurrent.x()/arX, m_posCurrent.y()/arY);
    }
}