728x90

지난 포스팅에서 안드로이드 스튜디오를 업데이트하고 플러터 플러그인을 설치해보았습니다. 추가된 플러그인을 통해 샘플 프로젝트를 만들고 실행을 해보았지만 예상대로 문제가 발생했고, 안드로이드 가상 장치에서 시험을 해볼 수 없었습니다. 무슨 문제가 있었던 것일까요?

 

안드로이드 스튜디오에서 플러터 프로젝트를 생성하고 기본 샘플 앱을 가상 안드로이드 기기로 실행했을때 발생한 에러 화면입니다. 뭔가 SDK와 관련된 라이센스가 제대로 적용이 안된 것 같은 에러메세지입니다. 바로 터미널을 실행하여 플러터 닥터 flutter docter 명령을 통해 문제점을 확인해 보았습니다. 명령은 터미널에서 flutter docter 를 입력하여 수행합니다. 

 

초록색 체크표시가 된 것들은 문제가 없는 부분들입니다. 느낌표로 출력된 내용을 보니 비주얼 스튜디오 코드를 위한 플러터 환경 구성 이후 변경된 것들이 좀 있어 보입니다. 가장먼저 Android toolchain 항목에 대한 명령을 통해 첫번째 문제를 해결해 보겠습니다. 

flutter doctor --android-licenses

 

위의 플러터 닥터 명령은 동의해야 하는 약관, 라이센스에 대한 확인을 해주는 명령입니다. 실행후 나오는 내용을 살펴보고 (영어입니다 -_-;) 동의한다는 의미로 y 키를 몇 번 눌러주면 됩니다. 다시 닥터를 실행해서 처리가 잘 되었는지 보겠습니다. 

오호라. 첫번째 Android toolchain 항목도 이제 초록색 체크로 바뀌었습니다. 플러터로 개발된 코드를 iOS 에서 실행할 수 있도록 하기 위해서는 Xcode 환경도 준비가 되어 있어야 합니다. 지난번에도 CocoaPods 설치하느라 고생했는데... 그래도 다시 한 번 해보았습니다. 

#  sudo gem install cocoapods
Password:
Fetching i18n-1.8.9.gem
Fetching tzinfo-1.2.9.gem
Fetching activesupport-5.2.4.5.gem
Fetching nap-1.1.0.gem
Fetching fuzzy_match-2.0.4.gem
Fetching concurrent-ruby-1.1.8.gem
...
...
Parsing documentation for gh_inspector-1.1.3
Installing ri documentation for gh_inspector-1.1.3
Parsing documentation for ruby-macho-1.4.0
Installing ri documentation for ruby-macho-1.4.0
Parsing documentation for cocoapods-1.10.1
Installing ri documentation for cocoapods-1.10.1
Done installing documentation for concurrent-ruby, i18n, thread_safe, tzinfo, activesupport, nap, fuzzy_match, httpclient, algoliasearch, ffi, ethon, typhoeus, netrc, public_suffix, addressable, cocoapods-core, claide, cocoapods-deintegrate, cocoapods-downloader, cocoapods-plugins, cocoapods-search, cocoapods-trunk, cocoapods-try, molinillo, atomos, CFPropertyList, colored2, nanaimo, xcodeproj, escape, fourflusher, gh_inspector, ruby-macho, cocoapods after 25 seconds
34 gems installed

 

자, 코코아포드 관련한 패키지들의 추가도 끝났으니 다시 flutter docter 를 실행해 봐야겠죠?

 

에러 메세지가 확~ 사라졌습니다. 이제 마지막으로 남은 것은 안드로이드 스튜디오에서 플러그인을 설치하는 일입니다. 에..? 플러그인? 분명히 설치했다고 생각했는데... 무슨 문제일까요? 일단 에러 메세지를 무시하고 코드를 안드로이드 에뮬레이터에서 실행해 보겠습니다. 희안하게도 문제 없이 실행이 됩니다. 

 

어렵지 않죠? 네, 저는 어렵습니다 ㅎㅎ. 일단 동작이 잘 되는 것을 확인했으니, 본격적으로 뭔가를 만들어 봐야겠습니다!

728x90
728x90

아따 많이도 업데이트한다...

 

어제는 간만에 Flutter로 코드 만들어 보느라 고생했고 오늘은 또 간만에 파이썬으로 코드 만드느라 고생중입니다. 그 사이에 무슨 일이 있었던 것인가... (빅써 없데이트!?) 갑작스레 새 코드 프로젝트를 만들기 위해 virtualenv 를 돌리는데 Library not loaded 에러가 발생합니다. 자연스레 pip 로 virtualenv 를 업데이트 해볼랬더니.. 어라? pip도 동작을 안합니다. 

% virtualenv
dyld: Library not loaded: /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
  Referenced from: /Library/Frameworks/Python.framework/Versions/3.6/Resources/Python.app/Contents/MacOS/Python
  Reason: image not found
zsh: abort      virtualenv
% pip
dyld: Library not loaded: /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
  Referenced from: /Library/Frameworks/Python.framework/Versions/3.6/Resources/Python.app/Contents/MacOS/Python
  Reason: image not found
zsh: abort      pip

 

뭔가 운영체제 업데이트가 되면서 symlink가 꼬인 느낌이라 과감히 brew 로 파이썬을 재설치 해보기로 했습니다. 의존성이 걸려있는 패키지가 너무 많은 탓인지 업데이트가 한참 걸리네요. 열심히 다운로드 받고 설치하는 동안 저의 맥북프로는 또 다시 이륙을 하고는 고도를 높여 나갑니다...

% brew install python
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 3 taps (homebrew/core, homebrew/cask and homebrew/services).
...
...
==> Installing python@3.9
==> Pouring python@3.9-3.9.2_1.big_sur.bottle.tar.gz
Error: The `brew link` step did not complete successfully
The formula built, but is not symlinked into /usr/local
Could not symlink bin/2to3
Target /usr/local/bin/2to3
already exists. You may want to remove it:
  rm '/usr/local/bin/2to3'

To force the link and overwrite all conflicting files:
  brew link --overwrite python@3.9

To list all files that would be deleted:
  brew link --overwrite --dry-run python@3.9

Possible conflicting files are:
/usr/local/bin/2to3 -> /Library/Frameworks/Python.framework/Versions/3.6/bin/2to3
/usr/local/bin/easy_install-3.9 -> /usr/local/Cellar/python@3.9/3.9.0_2/bin/easy_install-3.9
/usr/local/bin/idle3 -> /Library/Frameworks/Python.framework/Versions/3.6/bin/idle3
/usr/local/bin/pip3 -> /usr/local/Cellar/python@3.9/3.9.0_2/bin/pip3
/usr/local/bin/pip3.9 -> /usr/local/Cellar/python@3.9/3.9.0_2/bin/pip3.9
/usr/local/bin/pydoc3 -> /Library/Frameworks/Python.framework/Versions/3.6/bin/pydoc3
/usr/local/bin/python3 -> /Library/Frameworks/Python.framework/Versions/3.6/bin/python3
/usr/local/bin/python3-config -> /Library/Frameworks/Python.framework/Versions/3.6/bin/python3-config
==> /usr/local/Cellar/python@3.9/3.9.2_1/bin/python3 -m ensurepip
==> /usr/local/Cellar/python@3.9/3.9.2_1/bin/pip3 install -v --global-option=--no-user-cfg --install-option=--force --install-option=--single-version-externally-managed --install-option=--record=installed.txt --upgrade --target=/usr/local
==> /usr/local/Cellar/python@3.9/3.9.2_1/bin/pip3 wheel --wheel-dir=/usr/local/Cellar/python@3.9/3.9.2_1/Frameworks/Python.framework/Versions/3.9/lib/python3.9/ensurepip/_bundled /usr/local/Cellar/python@3.9/3.9.2_1/libexec/setuptools /us
==> Caveats
Python has been installed as
  /usr/local/bin/python3

Unversioned symlinks `python`, `python-config`, `pip` etc. pointing to
`python3`, `python3-config`, `pip3` etc., respectively, have been installed into
  /usr/local/opt/python@3.9/libexec/bin

You can install Python packages with
  pip3 install <package>
They will install into the site-package directory
  /usr/local/lib/python3.9/site-packages

See: https://docs.brew.sh/Homebrew-and-Python
...
...

 

brew 의 로그를 보면서 에러가 난 부분들을 집중적으로 살펴봅니다. 확실히 python 3.9 를 설치하는 과정에 link 연결이 원활하지 않은게 보이는군요. 설치가 끝나는대로 brew link 명령을 --overwrite 으로 돌려보는게 좋을 것 같습니다. 그나저나 설치는 언제 끝나나...하고 있는데 설치가 끝났네요. 자 한번 brew link 를 수행해 보겠습니다

% brew link --overwrite --dry-run python@3.9
Would remove:
/usr/local/bin/2to3 -> /Library/Frameworks/Python.framework/Versions/3.6/bin/2to3
/usr/local/bin/idle3 -> /Library/Frameworks/Python.framework/Versions/3.6/bin/idle3
/usr/local/bin/pydoc3 -> /Library/Frameworks/Python.framework/Versions/3.6/bin/pydoc3
/usr/local/bin/python3 -> /Library/Frameworks/Python.framework/Versions/3.6/bin/python3
/usr/local/bin/python3-config -> /Library/Frameworks/Python.framework/Versions/3.6/bin/python3-config
%
% brew link --overwrite python@3.9
Linking /usr/local/Cellar/python@3.9/3.9.2_1... 21 symlinks created.
%
%
% python3
dyld: Library not loaded: /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
  Referenced from: /Library/Frameworks/Python.framework/Versions/3.6/Resources/Python.app/Contents/MacOS/Python
  Reason: image not found
zsh: abort      python3

 

하아... 뭔가 잘 해결이 안되었네요. 분명 3.9 를 설치한 것 같은데 에러 내용의 중간을 보니 3.6을 참조하고 있는게 문제인 듯 싶습니다. python3 의 위치를 탐색해서 강제로 symlink 를 변경해 보도록 하겠습니다. 

% which python3
/Library/Frameworks/Python.framework/Versions/3.6/bin/python3
%
%
% cd /Library/Frameworks/Python.framework/Versions/3.6/bin/
% rm python3
%
% which python3
/usr/local/bin/python3

 

하하~! 요렇게 하니 이제 새로 설치된 python3.9 버전이 잘 실행이 됩니다. 그러나 여전히 virtualenv나 pip가 제대로 동작하지 않았습니다.

% python3
Python 3.9.2 (default, Feb 24 2021, 13:26:09)
[Clang 12.0.0 (clang-1200.0.32.29)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>

 

뭐가 문제일까 하다가... 문득 .bash_profile 에 추가되었던 PATH 정보가 생각나서 이 부분을 모두 제거하고 터미널을 재기동 해보았습니다. 그리고 나니 이제야 제대로 동작하는 virtualenv 와 pip..!! 개발 환경은 처음 설정이 늘 어렵고 번거롭고... 그런것 같습니다 ㅎㅎ. 비슷한 어려움을 겪는 분들이 계시다면, 

1. brew 로 python 패키지 업데이트
2. symlink 가 이상하게 걸려 있는지 확인
3. PATH 로 잡혀 있는 파이썬 디렉토리 확인

의 순서를 따르시면 문제를 해결하실 수 있을 것 같습니다!

 

728x90
728x90

플러터 개발환경을 안드로이드 스튜디오에 구성해 보도록 하겠습니다. 기억하실지 모르겠지만 비주얼 스튜디오 코드 Visual Studio Code 에 환경을 구성하는 법을 잠깐 소개드렸었죠? 어쩌다보니 그 사이 시간도 많이 흘렀고... 다시 플러터 작업을 시작하면서 이번엔 안드로이드 스튜디오에 환경을 만들어 보도록 하겠습니다. 

플러터 플러그인 설치

가장 먼저 필요한 것은 안드로이드 스튜디오입니다. 안드로이드 스튜디오의 설치는 이미 되어 있다는 가정하에 플러터 개발환경을 꾸미도록 하겠습니다. 안드로이드 스튜디오가 제공하는 플러터 플러그인을 설치하면 개발환경 구성이 쉽게 진행됩니다. 

Configure > Plugins

 

안드로이드 스튜디오를 실행하고 우측 하단의 <Configure>를 눌러 <Plugins>를 선택합니다. 플러그인 추가를 통해 플러터를 안드로이드 스튜디오에서 사용할 수 있게 됩니다. 플러그인을 선택하고 검색창에 flutter를 검색했더니...

아무런 플러그인이 검색되지 않았습니다. 설치되어 있는 안드로이드 스튜디오의 버전이 3.1.4로 꽤 낮은 편이라 플러그인에서 검색이 잘 안되는 것 같습니다. 친절하게 안내된 <Search in repositories>를 누르고 다시 flutter를 검색해 봅니다. 높은 버전의 안드로이드 스튜디오라면 플러터를 바로 찾으실 수 있었을겁니다.

네, 이번에는 잘 찾아졌습니다! 여러가지가 있지만 가장 눈에 띄는 것을 설치하려고 보니... 업데이트 날짜가 2018년 10월 2일이군요. 아무래도 느낌이 좋지 않으니 안드로이드 스튜디오를 업데이트하고 오도록 하겠습니다 ;;;

 

안드로이드 스튜디오 업데이트 

매번 느끼는 것이지만 새로운 개발 환경을 만드는 것은 참 스트레스입니다. 본 게임에 들어가기도 전에 환경 설정하고 Hello World 찍어보다가 시간이 다 가기 마련이죠. 이번에는 꼭 제대로 공부하겠다는 일념으로 (스스로를 속이며) 안드로이드 스튜디오를 업데이트 해봅니다. 

다행히 용량이 그리 크지 않네요. 최신버전과는 메이저 버전 넘버가 차이날 정도로 시대에 뒤떨어져 있는 안드로이드 스튜디오를 가지고 있었군요. 과감히 <Update and Restart>를 눌러 업데이트를 진행합니다. 자바도 업데이트하고... 여러가지로 컴퓨터가 고생을 합니다. 

친절히도 오래된 버전 삭제를 건의하길래... 재빨리 마음 변하기 전에 <Delete Directories>를 눌러줍니다. 잘가라 안드로이드 스튜디오 3.1아..!

 

다시 플러터 플러그인 설치 시도하기!

이제 정신차리고 다시 플러그인 업데이트를 시도해 봅니다. <Configure>메뉴에 옵션도 많아지고... 잘은 모르겠지만 버전업을 하니 UI도 막 이뻐지는 것 같고 뭐 그런 기분이가 듭니다. 플러터가 이번에는 잘 검색되겠죠?

다행히 이번에는 Flutter의 검색결과가 바로 똭~하고 나왔습니다. 다운로드 횟수가 8백만회가 넘어가는 가장 첫번째 검색결과가 우리가 찾는 플러그인입니다. 

우측 상단의 Install 버튼을 누르고 플러그인 설치를 진행하겠습니다. 아파트 네트웍이 느린지 아직 아이콘도 제대로 안뜬 플러그인들이 눈에 띄는군요. 일해라 SK브로드밴드!

플러터를 구성하는 필수 요소인 다트 Dart 언어용 플러그인도 따로 존재하나 봅니다. Required 이니 Install 을 눌러서 Dart 플러그인도 설치하도록 하겠습니다. 

하아.. 뭔가 많습니다. 다트를 설치하고나니 이번에는 개발 도구를 재기동 하겠다고 합니다. 배움의 길은 역시 멀고도 험합니다. Restart를 누르고 재기동을 수행합니다. 참 착하죠?

안드로이드 스튜디오가 재기동되고 나니 이전에 없었던 옵션이 하나 생긴 것이 보입니다. 바로 <Create New Flutter Project> 입니다! 감동적인 순간입니다. 드디어 플러터 프로젝트를 만들고 코드를 개발할 수 있는 준비가 되었습니다! 

To be continued...

#플러터 #flutter #androidstudio #ide #개발환경구성 #크로스플랫폼 #모바일앱 #앱개발 

728x90
728x90

CORS (Cross Origin Resource Sharing) 은 서로 다른 도메인 간에 리소스를 활용할 필요가 있을때, 어떤 규칙으로 누구에게 허용할 것인지를 정의하는 HTTP 표준의 일부입니다. 모던 브라우저들은 CORS 헤더에 대한 지원을 충실히 하고 있습니다만, 서버측에서는 어떤식의 구현이 필요한지, 그리고 커스텀 클라이언트를 사용하는 경우에는 어떤 요청을 보내는 것이 적절한지에 대해 오해도 많고 시행착오도 많습니다.

CORS 에 대한 기본적인 정의를 먼저 살펴보고 CORS 구현을 위한 RFC 규격을 살펴보면서 어떤 요청 헤더와 응답이 필요한지 살펴봄으로써, 혹시나 CORS 에 대하여 시행착오를 겪는 분들이 적어지기를 바라며 포스팅을 시작해 보도록 하겠습니다. 


CORS 란 무엇일까?

웹이 태동하고 급성장하던 시기에는 서로 다른 리소스를 가져다 쓰는 것에 대하여 큰 제약이 없었습니다. 하지만 리소스를 사용하는 것은 분명 서버측의 비용이 발생하는 일이고, 보안 관점에서도 접근하는 사용자를 적절히 통제할 필요가 생겼습니다. 이런 요구사항을 수용하기 위하여 정의된 것이 CORS (Cross Origin Resource Sharing, 서로 다른 원본 서버간의 리소스 공유에 관한 규칙) 입니다. 

2009년경에 출시된 파이어폭스 Firefox 3.5 와 사파리 Safari 4.0 에서부터 강화된 동일 오리진 정책 SOP (Same Origin Policy) 이 적용되기 시작했고 현재 시장에서 사용되는 대부분의 브라우저는 이 정책을 준수하고 있습니다. 이 즈음부터 XHR (XML Http Request) 을 이용해 서로 다른 원본 서버에서 리소스를 <비동기> 로 가져다 쓰는 것에 대한 혼란(?)이 시작되었다고 봐도 무방합니다. 

근래의 브라우저들에서는 Fetch 도 제공하기 시작했고 Fetch 역시 XHR 과 마찬가지로 CORS 의 영향권 아래에 있습니다. 따라서 CORS 에 대한 정확한 이해를 바탕으로 구현을 해야 커머셜 브라우저는 물론이고 커스텀 클라이언트 개발에 대응할 때도 불필요한 시행착오를 줄일 수 있습니다. 

브라우저보다 조금 늦게 (늘 그렇듯) 2010년에 Drafting 된 CORS

 

다른 Origin 에서 리소스를 가져오는 두가지 방법

JSONP 는 논외로 두고 다른 Origin 에서 리소스를 가져오는 방법은 앞서 이야기 한 것처럼 XHR 을 이용한 방식와 Fetch 를 이용한 방식으로 나뉘어 집니다. 많은 자바스크립트 프레임웍 (jquery, axios...) 도 이들을 래핑하고 있기 때문에 동일하게 CORS 규칙의 영향을 받게 됩니다. 

비동기로 리소스를 가져오는 방식은 다른 관점에서 보면 단순 요청 Simple Request 와 예비 요청 Pre-flight Request 로 다시 나뉘어 집니다. 이 두가지의 차이점은 간단합니다. 메소드와 헤더에 관한 규격들이 더 있지만, 일단 크게 아래의 구분이 있다는 점을 인식하는 것이 중요합니다. 

구분 내용
단순 요청 Simple Request - GET, POST, HEAD 메소드로 하나의 요청에 필요한 CORS 요청 헤더를 포함하여 전송
예비 요청 Pre-flight Request - OPTIONS 메소드를 이용하여 본 요청에 대한 스펙을 CORS 요청 헤더를 포함하여 전송
- 성공 응답을 받은 경우 본 요청을 전송

 

CORS 의 기본, Origin 요청 헤더

앞서 설명한 두 요청의 상세한 차이점은 다음 포스팅에서 소개할까 합니다. 절단 신공이라기 보다는... 두 요청의 공통 요소 중 하나인 Origin 헤더의 규격에 대해서 살펴보고 가는 것이 더 중요하기 때문입니다. 다른 Origin 으로 리소스를 요청하는 경우, 원래의 요청이 어떤 도메인에서 시작된 것인지를 다른 Origin 으로 알려주어야 할 필요가 있습니다. 이 때 사용하는 것이 Origin 요청 헤더입니다. 

가령 https://a-server.nopd-genius.com 이라는 도메인에서 XHR 혹은 자바스크립트 프레임워크를 이용하여 https://b-server.nopd-not.com 이라는 도메인으로 요청을 보내는 경우를 생각해 보겠습니다. 자바스크립트 코드는 첫번째 서버(a-server)에서 사용자 브라우저로 전달해 주었기 때문에, 이 코드가 만든 두번째 서버(b-server)로의 요청은 `Origin: https://a-server.nopd-genius.com` 이라는 헤더를 포함해야 합니다. 

이 요청을 받은 두번째 서버(b-server)는 Origin 값에 해당하는 정책을 확인하여 이를 CORS 응답 헤더로 내려주게 됩니다. 이 과정에서 Origin 헤더 값이 사전에 약속된 원본 도메인이 아니라면 에러 응답을 하거나 CORS 헤더 없이 응답하게 되어 결과적으로 브라우저에서는 응답을 사용하지 못하는 상황이 되게 됩니다. 

출처 : 모질라 CORS 문서 

 

그런데 말입니다, 모질라의 CORS 문서에서 발췌한 위의 내용은 한가지가 잘못되어 있습니다. RFC 의 규격 문서에 따르면 Origin 헤더의 값은 반드시 스킴 Scheme (http 혹은 https) 을 포함해야만 합니다. 위의 그림처럼 `Origin: foo.example` 로 던지면 규격에 대한 위반이 되게 됩니다. 왜냐하면 http://foo.example 과 https://foo.example 은 서로 다른 Origin 으로 활용될 수 있기 때문입니다. WHATWG 의 규격 문서를 보면 이 헤더의 규격은 아래와 같습니다. 

특정한 포트를 지정해주는 ":port" 는 필요 없는 경우 생략해 줄 수 있지만, 스킴은 생략 가능한 항목으로 명기되어 있지 않습니다. 따라서 Origin 요청 헤더는 위의 규격을 준수하여 전송할 필요가 있습니다. 모질라의 문서 그림도 업데이트가 되어야 하겠죠? ^^ 이렇게 Origin 헤더가 중요합니다. 

다행히도 근래의 모던 브라우저들은 CORS 요청을 하는 경우 항상 스킴을 포함한 Origin 요청 헤더를 보내주고 있습니다. 따라서 Origin 헤더 값은 상용 브라우저가 아닌 클라이언트를 사용하는 경우에 유의해 주시면 큰 문제는 발생하지 않을 것으로 생각됩니다. 다음 포스팅에서는 Simple Request 와 Pre-flight Request 의 요건에 대하여 보다 자세히 살펴보도록 하겠습니다. 


참고자료

 

교차 출처 리소스 공유 (CORS)

교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)는 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라

developer.mozilla.org

 

 

Cross-Origin Resource Sharing

Must be deployable to IIS and Apache without requiring actions by the server administrator in a configuration where the user can upload static files, run serverside scripts (such as PHP, ASP, and CGI), control headers, and control authorization, but only d

www.w3.org

 

 

cross-site xmlhttprequest with CORS – Mozilla Hacks - the Web developer blog

Editor's Note: This article sure is a popular one! The Fetch API is now available in browsers and makes cross-origin requests easier than ever. Check out this Hacks post or ...

hacks.mozilla.org

 

 

Fetch Standard

 

fetch.spec.whatwg.org

 

728x90

+ Recent posts