개요
웹 개발에 이어 어플 개발도 찍먹하기 위해, 플러터라는것을 써보기로 했다
이를 위해서 플러터 개발환경을 삽질하였는데, 약 2주간의 고생을 정리해보기로한다.
어떤식으로 삽질했는지 시간순으로 적어보도록 하겠다.
환경
삽질을 시작하기 전, 내 환경을 설명하자면
•
데스크톱
◦
cpu : i7
◦
ram : 16gb
◦
storage : 512gb ssd
◦
graphics : Intel Xeon + GTX1080 ti + GTX970
◦
os : Ubuntu
◦
display : none
•
노트북
◦
cpu : i5
◦
ram : 8gb
◦
storage : 256gb ssd
◦
graphics : Intel uhd + MX150
◦
os : Window
◦
display : 15.6inch
이렇게 되어있으며, 데스크톱은 모니터 없이 거실에 하루종일 켜두고 있다.
그래서 보통은 노트북에서 데스크톱으로 ssh로 원격으로 사용한다.
목표
노트북은 램이 처참히 부족해서 평소에도 90% 사용률을 보여주기 때문에,
왠만한 작업은 지금까지 해왔던대로 데스크톱에 원격으로 접속해 개발하고 싶었다.
•
위와같이 VScode 와 에뮬레이터를 같이 띄우는 개발환경을 만들고싶었다.
•
VSCode는 노트북에서 돌아가지만, Workspace 는 데스크톱이고,
•
에뮬레이터는 데스크톱에서 돌아가지만, 화면만 노트북으로 공유되는 형식이다.
•
즉, 노트북의 자원은 최소한으로 사용하고 모든 작업을 원격으로 하는것이다.
계획
일단 플러터 개발환경에 대해 아는것이 전혀 없기 때문에,
먼저 내 노트북에서 돌아가는 환경을 만들고 원격 개발 환경을 삽질해보기로 한다.
Local
개요
•
공식 Docs에 설명이 아주 잘되어있다.
•
플러터 SDK 를 깔고,
•
안드로이드 스튜디오를 깔고,
•
안드로이드 SDK 를 깔고,
•
에뮬레이터를 설치하고,
•
VScode 에서 실행하면 된다.
설정
1. flutter sdk 다운로드
•
D:\Dev\DevTool\Flutter 폴더 생성
•
sdk 다운받은거 압축 해제
2. PATH 수정
•
D:\Dev\DevTool\Flutter\bin PATH에 추가
•
where flutter dart 해서 적용확인
3. 안드로이드 스튜디오 설치
•
exe파일 다운받아서 실행하면 됨.
4. 안드로이드 SDK 설치
•
안드로이드 스튜디오 열고
•
오른쪽 밑에 Configure 누르고 SDK manage 클릭
•
Android SDK 중에서 API 29 선택 (가장 최근 버전)
•
Android SDK Command-line Tools 선택
•
Android SDK Build-Tools 선택
•
선택한 항목 설치
5. 에뮬레이터 설치
•
안드로이드 스튜디오 열고
•
오른쪽 밑에 Configure 누르고 AVD manage 클릭
목록에 안뜨는 오류
•
시스템 이미지 하나 다운
◦
원하는 시스템 이미지 설치
◦
이게 없으면 에뮬레이터가 돌아가지 않음
시스템 이미지 삭제 하는법
6. VScode extension 설치
•
Flutter 확장 설치
7. flutter doctor 실행
•
콘솔에서 flutter doctor 실행
•
필요한 dependencies 확인
SDK 인식 실패 오류
라이센스 오류
8. 실행 확인
•
VScode 명령 팔레트에서 Flutter: New Project
•
오른쪽 아래에서 에뮬레이터 설정
◦
위의 안드로이드 스튜디오에서 하나 만든거 해도 되고
◦
vscode에서 새롭게 만들어도되고
•
F5 로 실행
•
처음에 화면 뜨고 안드로이드 업데이트 기다리기
•
앱이 실행됨!!
Remote
개요
1. 삽질의 시작
•
목표를 달성하기 위해서, VScode와 에뮬레이터를 어떻게 원격으로 쓸수있는지 알아보았다.
•
VScode 는 Remote SSH 라는 확장을 사용하면 ssh를 통해서 원격으로 workspace를 쓸수있다.
•
그럼 에뮬레이터는 ...?
•
X11 forwarding 을 통해서 원격으로 GUI 프로그램의 출력을 볼수있다는것을 알게되었다. !!
•
그렇다면 마찬가지로 에뮬레이터도 노트북에서 충분히 볼수있다..!?
단순하게 생각했던 처음
•
위와 같이 하면 되지 않을까?
•
먼저 에뮬레이터를 데스크톱에 설치 해야한다.
2. 우매한 봉우리
•
Dockerfile을 열어보면 Flutter SDK, Android SDK, Emulator 설치까지 알차게 구성되어있는걸 알수있다.
•
정말 편리한 세상이다
•
README를 보면 kvm 과 xhost 가 필요하다고 한다.
이런식으로 작동할것이라고 생각했다.
•
기대에 부푼마음으로 Dockerfile을 build 하고 run 했다.
# build
docker build -t flutter_dev ./
# run
docker run -it -d \
--name flutter_dev \
--device /dev/kvm \
--device /dev/dri:/dev/dri \
-p 5222:22 \
flutter_dev /bin/bash
Bash
복사
•
ssh로 접속하고, kvm 권한을 주고, 에뮬레이터를 실행 시켰다.
service ssh start
chown $USER -R /dev/kvm
# display 환경설정
export DISPLAY=54b870f84509:10.0
flutter emulators --launch $FLUTTER_EMULATOR_NAME
Bash
복사
X server does not support XInput 2 오류
•
아쉬운대로 그래픽 가속 없이 돌려보았다.
avdmanager list avd # 에뮬레이터 확인
emulator -avd flutter_emulator # 그래픽 가속으로 실행
emulator -avd flutter_emulator -gpu swiftshader_indirect # 소프트웨어 가속으로 실행
Bash
복사
•
그랬더니 화면이 뜬다 !!
3. 잘못된 삽질
•
소프트웨어 가속이라서 그런지 상당히 느리고 솔직히 전혀 쓸만한게 못됐다.
•
그래픽 가속만 된다면 엄청 빠를것같았다.
•
OpenGL 이 GPU 가 필요하다는걸 알게되었으니, 아래와같이 작동한다고 생각했다.
•
OpenGL을 확인해 보았다.
◦
그래픽 가속 테스트를 위한 간단한 프로그램으로 glxgears 를 실행해 본다.
$ glxgears
libGL error: No matching fbConfigs or visuals found
libGL error: failed to load driver: swrast
Bash
복사
◦
위와 같은 오류가 나면서 톱니가 돌아가지 않는다.
◦
glxinfo 를 통해 OpenGL 다양한 정보를 확인할수있다.
$ glxinfo | grep "direct rendering"
direct rendering: No (LIBGL_ALWAYS_INDIRECT set) # 그래픽 가속 확인
Bash
복사
◦
그래픽 가속을 사용하지 못한다고 한다.
◦
inxi -G 를 통해서도 정보를 확인할수있다.
•
Docker에서 그래픽카드를 인식하지 못해서 그렇다고 생각했다.
◦
nvidia-docker 를 설치하고 gpu 옵션을 줘서 다시 실행해봤다.
◦
그러나 여전히 똑같은 오류가 뜬다.
•
알고 보니 host에서도 그래픽 가속이 안된다
◦
nvidia-smi 가 작동하는걸 보면 분명 그래픽카드가 잘 되는건데,, 이상하다.
◦
glxinfo 를 보면 opengl 랜더러로 인텔 내장 그래픽이 잡혀있고,
◦
glxgears 하면 위와 같은 오류가 나면서 톱니가 돌아가지 않는다.
◦
무언가 그래픽카드 드라이버가 단단히 잘못되었다...!!!
•
무한 그래픽카드 드라이버 삽질의 시작
◦
nvidia-settings 안 뜨고
◦
glxgears 안되고
◦
◦
이런저런 이유로 10번은 넘게 포맷했다.
4. 허무한 결론
•
glxinfo 를 보던중 이상한점이 있다.
$ glxinfo | grep render
direct rendering: No (LIBGL_ALWAYS_INDIRECT set)
GLX_MESA_multithread_makecurrent, GLX_MESA_query_renderer,
OpenGL renderer string: Intel(R) UHD Graphics 620
Bash
복사
•
내 데스크톱 인텔 내장 그래픽카드는 Intel Xeon 인데 터미널에는 Intel uhd 라고 나와있다 ??!
•
노트북의 nvidia 설정에 들어가서 VcXsrc의 opengl 랜더러를 MX150으로 바꿔봤다.
$ glxinfo | grep render
direct rendering: No (LIBGL_ALWAYS_INDIRECT set)
GLX_MESA_multithread_makecurrent, GLX_MESA_query_renderer,
OpenGL renderer string: GeForce MX150/PCIe/SSE2
Bash
복사
•
그렇다. 사실 데스크톱의 그래픽 드라이버는 전혀 문제가 없었다.
•
애초에 opengl에서 필요한 GPU 는 내 노트북 GPU 였던것이였다.
◦
어떻게 생각해보면 너무 당연한 얘기다.
◦
화면을 빠르게 출력하기 위해 GPU를 쓰는건데 그게 내 노트북에 달려있어야 의미가 있지
◦
다른곳에 달려있는게 무슨 소용이냐고...
•
지금까지 그래픽 드라이버 삽질하던것이 완전 헛수고였다.
•
export LIBGL_ALWAYS_INDIRECT=yes
Bash
복사
•
드디어 에뮬레이터 화면이 제대로 뜬다 !!!
•
하지만 여전히 엄청 느리다...
5. 알고보니
•
X11 는 opengl 명령어를 전달하지 못한다
◦
그렇기 떄문에 X11과 함께 GLX 를 통해서 opengl 명령어를 전달한다.
◦
◦
만약 indirect 가 아닌 direct 모드일경우 host의 cpu를 통해서 랜더된다.
◦
이제 오류는 안나지만 여전히 그래픽 가속이 안된다. (??)
~ glxinfo | grep "direct rendering"
direct rendering: No (LIBGL_ALWAYS_INDIRECT set)
Bash
복사
◦
Xming의 유료버전에서는 잘 작동한다고 한다.
◦
결국 돈주고 사야된다.
◦
그리고 애초에 MX150 으로는 좋은 성능을 기대하기 힘들다.
•
아무리 그래도 엄청 느렸던 이유
Mesa는 그 자체로 OpenGL API의 지원을 위한 다양한 backend를 가지고 있다. 세 가지 CPU를 기반으로한 구현체가 있는데, swrast(낡고 오래되고, 더 이상 사용되지 말아야 할 것), softpipe(느리다), llvmpipe(잠재적으로 빠르다).
◦
이 오류가 더이상 뜨지 않는걸로 보아서는 CPU 를 기반으로한 swrast 로 랜더 되었기 떄문에 상당히 느린것같다.
◦
반면에 위의 도커 이미지를 실행해보면, llvmpipe 를쓰기 떄문에 같은 CPU 기반이지만 속도가 상당히 빠르다.
◦
아쉬운대로 이것을 써도 전혀 문제 없을것같다.
6. 결론
무작정 삽질할게 아니라 차근차근 알면서 삽질하자.
아니면 이렇게 아무의미 없이 2주 날린다.
•
최종적으로 두가지 방법이 있다.
•
SSH를 통한 방법
◦
노트북에 별도의 VirtualGL Client 가 필요하다.
◦
cywin 을 쓰면 된다.
◦
VNC 보다는 조금 느리다.
•
VNC를 통한 방법
◦
노트북의 브라우저를 통해서 간편하게 사용가능하다.
◦
구성이 조금 복잡하고, 브라우저를 사용하기때문에 궁극적인 목표는 달성하지 못한다.
◦
화질이 조금 떨어진다. ㅠㅠ
VNC
1. Docker Image 생성
•
1년전쯤에 선조들이 다 삽질해뒀다. 그냥 잘 써먹기만 하면된다.
•
아래의 링크로 들어가서 시키는대로 recipe-wzi 이미지를 만든다.
•
•
OS와 cuda 버전은 아래 링크를 통해서 정확히 알수있다.
2. Dockerfile 생성
•
vscode 에서 접속하기 위한 ssh 설치
안드로이드 스튜디오 설치
Flutter SDK 설치
FROM recipe-wiz
ENV USER="docker"
ENV FLUTTER_CHANNEL="stable"
ENV FLUTTER_VERSION="1.22.4"
ENV FLUTTER_URL="https://storage.googleapis.com/flutter_infra/releases/$FLUTTER_CHANNEL/linux/flutter_linux_$FLUTTER_VERSION-$FLUTTER_CHANNEL.tar.xz"
ENV FLUTTER_HOME="/home/$USER"
ENV PATH="$FLUTTER_HOME/bin:$PATH"
#install dependencies
ENV DEBIAN_FRONTEND="noninteractive"
RUN apt update \
&& apt install -y curl \
unzip \
sed \
git \
openssh-server \
&& rm -rf /var/lib/{apt,dpkg,cache,log}
#ssh
RUN mkdir /var/run/sshd \
&& mkdir /root/.ssh \
&& chmod 700 /root/.ssh \
&& ssh-keygen -A \
&& sed -i "s/^.*PasswordAuthentication.*$/PasswordAuthentication no/" /etc/ssh/sshd_config \
&& sed -i "s/^.*X11UseLocalhost.*$/X11UseLocalhost no/" /etc/ssh/sshd_config
COPY authorized_keys /root/.ssh/authorized_keys
# android studio
RUN apt-get update \
&& apt-get -y install software-properties-common \
&& add-apt-repository ppa:maarten-fonville/android-studio \
&& apt update \
&& apt-get -o Dpkg::Options::="--force-overwrite" -y install openjdk-8-jdk \
&& apt install -y android-studio
RUN useradd -s /bin/bash -m $USER \
&& adduser $USER sudo \
&& echo "$USER:$USER" | chpasswd \
&& echo "$USER ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers \
&& mkdir /home/$USER/.ssh \
&& cp /root/.ssh/authorized_keys /home/$USER/.ssh \
&& chown $USER -R /home/$USER/.ssh \
&& echo "export PATH=$PATH" >> /etc/profile
USER $USER
WORKDIR /home/$USER
RUN ln -s /opt/android-studio/bin/studio.sh /home/$USER/android-studio.sh
# flutter
RUN curl -o flutter.tar.xz $FLUTTER_URL \
&& mkdir -p $FLUTTER_HOME \
&& tar xf flutter.tar.xz -C /home/$USER \
&& rm flutter.tar.xz \
&& flutter config --no-analytics \
&& flutter precache \
&& yes "y" | flutter doctor --android-licenses \
&& flutter doctor \
&& flutter update-packages
EXPOSE 22
EXPOSE 40001
CMD ["/bin/bash", "-c", "chown docker -R /dev/kvm && service ssh start && /usr/local/bin/start_desktop.sh"]
Docker
복사
3. Docker 실행
•
ssh 접속을 위해 pubkey를 Dockerfile 과같은 위치에 복사한다.
•
Docker build 후에 run 한다.
cp ~/.ssh/authorized_keys authorized_keys
docker build -t flutter_dev .
Bash
복사
•
쉘스크립트로 만들어서 실행하는것을 추천!
•
vi run.sh chmod 777 run.sh
#!/bin/bash
pkill xinit
export DISPLAY=:0
xinit &
docker run -it -d \
--runtime=nvidia \
--name=flutter_dev \
--security-opt seccomp=unconfined \
--init \
--privileged=true \
-p 7777:40001 \
-p 5222:22 \
-e DISPLAY=:1 \
-v /tmp/.X11-unix/X0:/tmp/.X11-unix/X0:ro \
-v /etc/localtime:/etc/localtime:ro \
-v /share-docker:/share-docker \
flutter_dev
Bash
복사
4. Android Studio 설치
•
브라우저에서 포트 7777 로 접속
•
터미널 열고 vglrun ./android-studio.sh 실행
•
안드로이드 스튜디오 설치
•
SDK 와 에뮬레이터가 같이 설치된다.
5. VScode extension 설치
•
remote SSH 확장 설치
•
VSocde에서 ssh 로 접속후 Flutter 확장 설치
6. 실행 확인
•
안드로이드 스튜디오를 통해서 에뮬레이터 실행
•
VScode 명령 팔레트에서 Flutter: New Project
•
오른쪽 아래에서 에뮬레이터 연결 확인 (인식안되면 vscode 재시작)
•
F5 로 실행
•
처음에 화면 뜨고 안드로이드 업데이트 기다리기
•
앱이 실행됨!!
SSH
1. VNC 개발환경 설정
•
위의 vnc 개발환경 설정을 그대로 따라한다.
•
안드로이드 스튜디오를 설치하고
•
VSCode 설정도 완료해야한다.
2. SSH 및 기타 설정
X11Forwarding yes
X11UseLocalhost no
sudo ln -s /home/$USER/Android/Sdk/emulator/emulator /usr/local/bin/emulator
Bash
복사
3. 윈도우에서 접속
•
Xserver로 Xming 대신에 Cygwin 을 사용할것이다.
•
Cygwin setup 파일 다운로드 및 실행
•
install from local directory 로 설치 진행
•
패키지 설치
◦
xorg-server
◦
xinit
◦
xlaunch
◦
virtualgl
•
XLaunch 실행
•
Cygwin 실행
# 환경변수 설정
export DISPLAY=:0
# 접속
vglconnect -s -force developer@192.168.150.23 -p 5222 -i /cygdrive/d/Dev/DevTool/SshKey/ubuntu
Bash
복사
4. 에뮬레이터 실행
•
희안하게 안드로이드 스튜디오를 켜서 에뮬레이터를 실행시키면 하드웨어 가속이 잘 되지 않는다.
•
터미널로 직접 에뮬레이터를 실행시킨다.
# 환경변수 잡혔는지 확인
echo $DISPLAY
# vgl 화면은 host를 잡도록함 + 압축안하게
export VGL_DISPLAY=:0
export VGL_COMPRESS=jpeg
# 실행가능한 에뮬레이터 확인
emulator -list-avds
sudo chown $USER -R /dev/kvm
# 에뮬레이터 실행
vglrun emulator -avd Pixel_3a_API_30_x86 -gpu host
Bash
복사
5. 실행 확인
•
VScode를 실행시키고 F5 눌러서 확인해본다.
•
잘된다!!
SSH 속도 향상
•
Xpra 로 X11 통신 속도 향상
•
vulkan 으로 에뮬레이터 자체 속도 향상