Search
Duplicate

원격 플러터 개발 환경 삽질

개요

웹 개발에 이어 어플 개발도 찍먹하기 위해, 플러터라는것을 써보기로 했다
이를 위해서 플러터 개발환경을 삽질하였는데, 약 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 오류
그러나 여전히 창이 안뜬다.
찾아보니까 에뮬레이터는 OpenGL 로 화면에 렌더링하는데,
vm 가속(KVM)그래픽 가속(GPU)으로 성능을 높인다고 한다.
vm 가속은 잘 되기때문에 그래픽 가속이 안되는것같다.
developer@ae60df2defec:~$ emulator -accel-check # kvm 확인 accel: 0 KVM (version 12) is installed and usable. accel
Bash
복사
아쉬운대로 그래픽 가속 없이 돌려보았다.
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 안되고
자꾸 부팅중에 or 꺼지다가 멈추고 (그래픽카드가 2개라서 그랬다.)
이런저런 이유로 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 명령어를 전달한다.
이때 GLX을 통해서 하드웨어 가속을 사용하기 위해 이 설정이 필요했던것이였다.
만약 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 기반이지만 속도가 상당히 빠르다.
아쉬운대로 이것을 써도 전혀 문제 없을것같다.
VirtaulGL 을 쓰면 호스트의 자원으로 그래픽 가속을 사용할수있다.
아무래도 1080ti 가 있는데 MX150 쓰는건 매우 낭비이기 떄문에 매우 필요하다.
원리는 대충 이러하다. GLX 프로토콜을 중간에 낚아채서 3D X Server로 넘겨주고,
원래 어플리케이션의 OpenGL 명령어가 Host의 GPU를 쓸수있도록 해준다.
그렇게 GPU에서 랜더된 결과(이미지)를 Client로 송출하는 형식이다.
Client 에 랜더된 결과를 보내주는 2가지 방법이 있다.
SSH를 통해서 보내주는방식과, VNC를 통한방법이다.

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 으로 에뮬레이터 자체 속도 향상