지난 글 (https://uaremine.tistory.com/69)에서
1) 텔레그램 봇 생성
2) 로컬 개발에 필요한 환경 설정 (Visual Studio Code, Python with pyenv, azure-functions-core-tools 설치
3) 로컬 프로젝트 생성
까지 해봤다.
이번에는 로컬에서 프로젝트를 Azure에 deploy 하는 것까지 해보자.
(텔레그램은 언제...)
로컬 프로젝트폴더에서 pyenv which python 해보면 ~/.pyenv/versions/3.9.11/bin/python (pyenv로 설치한 3.9.11) 으로 할당되어 있다. (pyenv global 3.9.11 로 설정해놓아서)
> mkdir agent46
> cd agent46
> pyenv which python
/Users/uaremine/.pyenv/versions/3.9.11/bin/python # pyenv로 설치한 3.9.11 이 이 폴더의 기본 python이다.
> code .
로컬 프로젝트 생성할 때 Python Interpreter 환경을 물어보는데, 특별히 지정하지 않으면 프로젝트 폴더 아래에 Python을 새로 설치한다.
그것을 원하지는 않으니 pyenv로 설치한 3.9.11 버전을 사용하도록 pyenv which python 하면 나오는 python 경로를 입력해보자.
이렇게 하면 로컬 프로젝트 폴더의 .venv/bin/python 이 pyenv 로 설치한 ~/.pyenv/versions/ 아래의 버전으로 사용된다.
로컬 프로젝트 생성 후에 정상적으로 실행되는지 F5 눌러보면
Executing task: .venv/bin/python -m pip install -r requirements.txt
source /Users/uaremine/VisualStudioCode/python/agent46/.venv/bin/activate
Requirement already satisfied: azure-functions in ./.venv/lib/python3.9/site-packages (from -r requirements.txt (line 5)) (1.12.0)
WARNING: You are using pip version 22.0.4; however, version 22.3.1 is available.
You should consider upgrading via the '/Users/uaremine/VisualStudioCode/python/agent46/.venv/bin/python -m pip install --upgrade pip' command.
* Terminal will be reused by tasks, press any key to close it.
* Executing task: . .venv/bin/activate && func host start
Found Python version 3.9.11 (python3).
Azure Functions Core Tools
Core Tools Version: 4.0.4483 Commit hash: N/A (64-bit)
Function Runtime Version: 4.1.3.17473
Functions:
agent46_localfunc: [GET,POST] http://localhost:7071/api/agent46_localfunc
For detailed output, run func with --verbose flag.
이렇게 python 3.9.11 버전을 이용해서 로컬 functions 가 생성되었다.
브라우저에서 http://localhost:7071/api/agent46_localfunc?name=hello URL을 불러보면
이렇게 잘 실행이 된다.
그렇다면 이것을 Azure에 deploy 해보자.
Azure Extension 의 WORKSPACE 항목에서 Deploy To Function App... 을 선택하면 될 것 같지만, "No matching resources found." 에러가 발생한다.
아직 Azure 에 이 프로젝트를 실행할 리소스를 만들어두지 않아서 그렇다.
RESOURCES 항목에서 + 버튼을 누르면 Create Function App in Azure.. 를 실행할 수 있다.
Azure에 만들 앱 이름을 입력하고, Python 3.9 를 runtime staack 으로 선택해준다.
location은 적당히 원하는 곳으로 선택하면 되는데, 개발할 때는 Korea 보다는 US로 하는게 좋더라. Korea 에서는 선택하지 못하는 옵션이 가끔 있다. 대략 Central US로 선택하고 잠시 기다리면 뙇! Azure에 functions app 이 하나 만들어진다.
Visual Studio Code 의 RESOURCES 항목에서 Function App 을 보면 빈 앱이 하나 생성된 것을 볼 수 있고, Azure Portal에서도 확인할 수 있다.
Function App 은 생성되었지만, 아직 function 은 안 만들었으니 App URL (이 경우에는 https://agent46.azurewebsites.net) 을 방문하면 앱이 만들어졌다는 내용만 나타난다.
그럼 이제 로컬에 만들어두었던 프로젝트를 이 Function App에 deploy 해보자. 확인을 위해 __init__.py 파일의 Response 를 아무렇게나 바꿔본다.
if name:
return func.HttpResponse(f"Hello, {name}. This HTTP triggered function FROM LOCAL PROJECT executed successfully.")
else:
return func.HttpResponse(
"This HTTP triggered function FROM LOCAL PROJECT executed successfully. Pass a name in the query string or in the request body for a personalized response.",
status_code=200
)
자, 이제 다시 Deploy to Function App... 을 선택하고, agent46 을 골라주면 잠시 후에 디플로이가 완료되고, 아까 비어 있던 리모트의 Functions 하위에 로컬에서 만들었던 agent46_localfunc 가 추가되어 있다.
브라우저에서 이 function을 실행해보자.
https://agent46.azurewebsites.net/api/agent46_localfunc
를 호출하면 되어야 할 것 같지만, 401 에러가 난다.
Shift-CMD-P 후에 Azure Functions: Copy Function Url 을 선택하면
https://agent46.azurewebsites.net/api/agent46_localfunc?code=IJJi8.........zATlJ-RZTAzFu4baGRQ%3D%3D
이런 URL이 복사된다. 잘 보면 code 라는 파라미터가 추가되어 있다.
Function App 을 생성할 때 Authorization Level 을 Function 으로 설정했기 때문에 Function Key를 파라미터로 넘겨줘야 하는 것이다. Authorization Level 을 Anonymous 로 선택하면 code 없이 function 앱이 실행된다.
Function Key 는 위의 경우처럼 Visual Studio Code 에서 Copy Function Url 로 가져올 수도 있고, Azure Portal에서도 알아낼 수 있다.
Function App 이 아니라 Function App 하위에 새로 생성한 Function (이 경우에는 agent46_localfunc) 의 Function Keys 항목에서 찾을 수 있다.
이 URL을 호출하면
이렇게 로컬 프로젝트에서 만들어준 소스가 Azure 상에 잘 deploy 되어 있음을 확인할 수 있다.
텔레그램 봇과는 큰 상관 없지만, 이 URL을 또 잠깐 보면
https://<Function App 이름>.azurewebsites.net/api/<Function 이름>?code=<Function Key>
이렇게 되어 있다.
이것은 Azure function의 routePrefix 기본 값이 "api" 이기 때문인데, (https://docs.microsoft.com/en-us/azure/azure-functions/functions-host-json) 필요 없는 api 를 없애고 싶다면,
host.json 파일에 extension > http > routePrefix 값을 추가해준다.
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
}
},
"extensions": {
"http": {
"routePrefix": ""
}
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[3.*, 4.0.0)"
}
}
이렇게 하고 로컬에서 실행해보면 function URL이
Functions:
agent46_localfunc: [GET,POST] http://localhost:7071/agent46_localfunc
이렇게 "api" 가 제거된 형태로 나타난다.
리모트(Azure)에도 deploy 해보자.
https://agent46.azurewebsites.net/agent46_localfunc?code=Icode=IJJi8.........zATlJ-RZTAzFu4baGRQ%3D%3D
Azure 에서 돌아가는 Function 의 URL에도 route prefix "api" 가 빠져서 동작한다.
오늘은 여기까지 하고, 다음에는 드디어 (진짜) 텔레그램 연동.