닷넷코어를 쓰는 개발자의 최근 프로젝트 삽질기 공유합니다.
각 단계에서 워낙 많은 삽질을해서 시간순서로 얘기하진 않겠습니다.
ChatGPT 덕을 많이 보았으나, 탓에 더 많은 삽질도 했습니다 (진실속에 거짓을 잘 숨기는 AI).
사실 코딩문제보다 개발환경과 배포환경, 문제해결이 많은 부분을 차지했어요. DevOps와 CI/CD 대신해주는 AI가 나와야합니다…
프로젝트 결과
- A서버: 닷넷으로 만든 Playwright 사용한 콘솔앱. 쇼핑몰에 들러서 스크린샷찍고 목적지서버 목록이 적힌 URL의 API 엔드포인트로 전송 (JWT인증). 크론탭스케줄로 하루 열번 돌아감.
- B서버: 워드프레스 홈피 B의 라이브 서버. 워드프레스에달린 RestAPI사용한 플러그인을 개발(PHP), JWT토큰 발급 및 A서버로부터 오는 스크린샷파일을 받아서 홈페이지에 표시.
소요기간
프로젝트를 마음먹고 닷넷코어 일부 공부하고 도커공부하고, 삽질등 5주 걸렸습니다.
하고싶었던 계획
“어차피 몇번 안돌릴 닷넷앱 공짜로 돌리고 싶다! AWS 람다 무료사용가능하겠다!” 라는 생각이 저를 파멸로 몰더군요. 결국 포기하고 위에 결과가 되었네요.
이거하려고 굉장한 삽질을 했지만, 그 얘기는 아래에…
최초 계획
원래는 A와 B가 역할이 반대였어요. 닷넷앱은 쇼핑몰스크린샷 찍고 저장하고 잇고 API를 열고 있고, B서버가 요청해서 가져가는 식.왜그랬는지 모르지만 진지하게 생각을 안했기때문에 일단 그렇게 생각하고.
워커서비스를 계획했습니다. 하지만 그냥 콘솔앱으로 잠깐실행하고 끝내는걸로 변경.
일단 API는 대충알기때문에 인증을 고민했죠.
“닷넷에서 JWT는 어떻게 하는거지?” 유튜브영상 20개 찾아봄. 이과정에서 배운 것 닷넷으로 Key Gen, 페이로드 구성하기.
“닷넷 코어 API 어떻게 만들더라? 예전에 MVC에 있었는데?” 지난기억보다 시간이 오래 지났다보니 닷넷코어 minimal API란게 나왔더군요. 이젠 swift 서버나 node.js 에서처럼 API 만들기 간편해졌네요.
유데미에서 “헬로 마이 뿌렌~” 하는 인도인 유료강좌 끊고 영상 60개 완주.
했지만 결국 A -> B로 바꾸었다보니 이번프로젝트에는 거의 무쓸모한 시간이었네요. 좋은거 많이 배웠습니다 (하지만 그뿐)
A -> B로 바꾼이유는 AWS 람다를 쓰기위한게 컸어요.
별도 서버에 배포한 이유
결과물이 워드프레스 B에서 필요한거라 그 하나의 서버에서 하면될텐데 분리한 이유는 스크레이핑 라이브러리가 성능을 꽤 잡아먹는다는 얘기를 들어서였고, 실제로 그러했어요.
본래 생각했던 AWS 람다는 그러기위해서 아주 좋은 수단이었죠.
B서버의 워드프레스는 안그래도 방문자가 많아져서 일주일에 한번씩 터지고 있었고 업그레이드하기엔 돈 아까워서 안하고 말이죠.
셀레늄: 본래 하려했던 스크레이핑 라이브러리
프로젝트 시작전에는 Playwright를 몰랐습니다. 중간에 알게되었고 적용할 맘은 없었어요. 왜냐면 셀레늄이 유명하고 자료도 많고 그러니까요.
셀레늄은 닷넷없으면 파이썬코드를 보면서 닷넷으로 개발하면 될정도로 사람들 파이썬으로 많이 써놨죠.
하지만! 데모앱을 돌리는데 문제가 생겼습니다. 닷넷 문제라고는 생각안하지만 이과정에서 Playwright로 전환하게 되었어요. 그리고
- Playwright에대한 무지와
- 닷넷코어에대한 무지와
- 거의 누구도 그렇게 쓰지않는 환장의 조합과
- 저만의 괜한 고집
이 뭉쳐서 제 머리카락을 한 웅큼 뽑아갔습니다(내 소중한 머리카락!). 이얘긴 또 나중에….
셀레늄에서 문제는 제가 부족한 탓이 크겠지만 탐탁지 못한 해결만 했습니다.
서버는 아시듯이 디스플레이가 없습니다. 일단 Headless로 돌릴때 문제가 생겼습니다.
응답시간 허용 1분 해도 타임아웃되거나 쇼핑몰 스샷이 하얗게만 찍히더라고요.
로컬에서 Headed로 돌리면 그래도 찍히는데요. 로컬에서도 headless로 돌려보니 안되더라고요.
이 이유를 왜 블럭된다고 생각했는지… 자료검색하다보니 셀레늄 클라우드플레어 우회방법 이런게 나와서 그만…
Playwright로 전환 후의 얘기지만 셀레늄은 결국 서버에 가상디스플레이를 붙여 Headed로 돌렸습니다. 잘되는거 확인만하고 버렸지만 그렇게 되었네요.
Playwright로 전환
셀레늄이 동작안되는 과정에서 Playwright란걸 알게되고 전환했습니다. “MS에서 만들었다고? 닷넷에서된다고?”
닷넷코어에 포함된 것은아니고 써드파티 누겟패키지(라이브러리)이지만, 그 “써드”가 MS라는 것 (읭?).
어쨌든 셀레늄건으로 Headless모드가 블럭된다고 생각하고 요청헤더 바꿔보고 생 난리를 치는데 하루를 날리고 결국 깨달은 사실: 서버성능이 구렸던 것이었습니다.
Playwirght도 대충 배워서 데모앱 만들고 돌리는데 맥에선 4초만에 되었거든요. 이것도 서버에 올리고하니 응답없음…
혹시? 하고 다른 가벼운 사이트 접속해서 찍어보니 잘되더라고요. Playwright도 셀레늄도….
그런데 쇼핑몰웹페이지가 한참느리니까 응답이없던것… 왜 생각을 못했을까요. Timeout 이라고 나오거든요(바보).
맥은 맥스튜디오인 반면 서버는 500mb 램에 1vCPU.. 후…. “아 맞다, 서버성능이 원래 구리지!”
테스트서버 띄운다고 돈아낀다고 한달 $3.5짜리 만들었거든요. 셀레늄으로 삽질한 거의 모든 시간이 이때문이었던거예요.하…
응답허용시간을 하~~~안참 높여놓고하니 Headless로 스샷 찍히더군요. 그러나 셀레늄은 여전히 못 찍었어요. 이때즘은 셀레늄 더해보고 싶은 마음은 있었으나 이미 대안을 찾아서 버렸죠.
Playwright는 성능이 좋다는 얘기를 들었지만 그것도 하드웨어가 바쳐줄때 얘기였어요.
국내 쇼핑몰 페이지 완전히 띄우고 스샷찍어 저장하는데 30~ 100초 걸리더군요.
1GB짜리 서버로 바꾸고 하니 10~20초. 원활이 돌리기위한 최소사양은 1GB 1vCPU로 결론지었어요.
문서를 잘 읽자
저는 영어를 잘 못할뿐이지 그래도 영어를 읽을 줄아는 개발자기때문에 Playwright 문서를 찾아 읽었거든요. 근데 영어로 쓰여진건 왜그리 읽기 귀찮을까요? 대충 읽은 자는 삽질을 할 뿐이죠.
Playwright는 node.js로 만들어져있습니다.
MS가 node.js로 만들어서 무려 닷넷용, 파이썬용으로 파생시켰더군요. 그건 그렇다치고 전 아예첨부터 닷넷용으로 개발했을 주 알았는데 실상은 그냥 node.js였습니다 (MS가 닷넷으로 다시 안만들고 래핑만 한거니?)
이사실을 생각도 못하고 처음 읽던게 “Playwright”라고 써진 온라인 문서거든요? <Playwirght 웹브라우저> 설치부분때문에 애를 먹었어요. 만들기도 괴상하게 만들어가지고는 …
셀레늄과 마찬가지로 웹브라우저 바이너리가 필요한데요. 일단 그걸 설치해야죠.
알고보니 닷넷 누겟패키지는 Playwright라고만 써있지만 <Playwright for .NET> 이고 이에대한 문서가 따로 있었어요.
<Playwright> 써진 온라인 문서는 node.js 용이었어요 (for Node.js라고 써놓던가!)
저는 닷넷프로젝트를하면서 node.js 개발환경의 웹브라우저 설치방법을 읽고 있던거죠. 여기부터 완전폭망이었던거죠.
배포환경에 개발도구가 왜 필요해?
라는 저의 고집이 있었어요. 닷넷코어는 닷넷런타임만 설치되어있으면 배포앱이 돌아갑니다. 아니, self-contained로하면 배포머신에는 런타임도 필요가 없죠.
위에 얘기했듯 저는 node.js용 문서를 보고 있었기 때문에! 제가 읽은 웹브라우저를 설치하는 방법이 npm이 필요했어요.
문서에 나온대로 터미널에
$ npx 플레이라이트 인스톨
하라대요. chatGPT도 그렇게 얘기해줬어요. 그랬다니까요. chatGPT도 닷넷용과 node.js용 Playwright를 구분못하고 있었습니다.
npx 명령어를 쓰려면 npm이 설치되어야하고 이것은 node.js를 설치하면 함께 설치되는 것이죠.
논리적으로 생각해보세요. 제 상황에 닷넷프로젝트를 개발하는데 왜 node.js 개발환경을? 이상하잖아요. 물론 제가 다른문서를 읽고있는 멍청이었을뿐이지만요.
그래요 양보해서 로컬컴은 개발컴이니까 설치했죠. 근데 배포머신에도 개발도구를? 절대 그렇게는 안되죠. 저는 이걸 람다에 올려야한고요.
그래서 node.js를 안쓰고 웹브라우저를 설치할 방법을 모색했고 방법은 있었어요. 닷넷 SDK만으로도 가능한 Playwright CLI가 있더군요. 이것도 SDK가 필요해? 왜때문에!!
Playwright 웹브라우저 설치 삽질
이과정에서 저 Playwright for .NET 문서가 따로 있다는 사실을 알게되고 이제 node.js를 철저히 배제하기로하고 닷넷 SDK도 안쓰고 웹브라우저를 설치할 방법을 모색했습니다.
chatGPT에게도 농락당하며 삽질을 이어갔죠.
웹브라우저 설치가 굉장히 골때렸는데 만든놈을 만나면 인터넷 금지형에 처해야한다고 생각했습니다.
어떤 스크립트를 실행시키고 그 스크립트가 C# 코드를 실행시키고 결국 라이브러리에 내장된 node.js 스크립트가 웹브라우저를 설치하는 구조였습니다.
애초에 node.js부터 시작된 라이브러리라서 node.js로 개발하는거면 그냥 js가 웹브라우저를 설치하는데요. 저는 “닷넷개발중이니까 node.js 안쓰겠다!”라고 한 고집이 있었던거죠.
for .NET은 MS가 MS의 파워스크립트 파일을 여기 껴넣었네요. 파워스크립트 명령어로 그 스크립트를 실행하고 그게 결론적으로 node.js로 웹브라우저 설치… 대충 추정한 바로는 그랬어요.
그러기위해 필요한 것은 바로, MS의 파워스크립트 콘솔 앱이죠. pwsd 명령어를 쓰려면 설치해야했어요.
macOS(개발머신)에서나, 우분투(배포머신)에서나 말이죠. node.js를 설치안하려했더니 또 뭘 설치해야하네요. 파워스크립트 설치하기 개 싫었죠(고집).
결국 알지도 못하는 파워스크립트 코드를 chatGPT한테 물어서 위의 사실을 추정하고 결국 같은기능을하는 셸스크립트파일을 찾아냈어요. (셸스크립트는 유닉스 스크립트라서 macOS나 리눅스나 기본으로 실행가능).
웃긴게 이 파일은 닷넷프로젝트에서 ‘빌드’든 ‘배포’든 해야 나오는 파일이었어요(야!!!)
그냥 Playwright 웹브라우저 바이너리를 포함하자
결국 웹브라우저를 설치해야하는 거였지만요, 위에 셸스크립트를찾아내기 전에는, 바이너리 자체를 같이 배포해야겠다고 생각했어요. 셀레늄의 경우 웹브라우저를 따로 설치과정없이 유닉스 실행파일로 빌드된 걸 포함하면 그만이었거든요.
그런데 MS는 바이너리 파일을 배포하고있지 않았어요. 문서에 이렇게 써있더군요.
“(위의 제가한 삽질을 지나) 설치명령어를 수행하면 MS의 CDN서버에서 바이너리를 다운 받는다” 그리고 그 주소는 “안알려줌”
그래서 그 바이너리 파일을 직접얻기위해서 저는, 닷넷앱을 빌드하고 배포해서 우분투서버에 올리고 거기서 설치명령어를 수행해서 나오는 linux용 바이너리를 다시 내컴에 다운받아서 배포폴더에 포함시켰죠. macOS에서 설치명령넣으면 macOS용 바이너리만 나오니 서버에 직접 올려 설치한거죠. 좀 빡치더라고요.
리눅스와 시스템디펜던시
삽질의 가장 큰 부분을 차지했던 디펜던시 설치를 얘기하지 않을 수가 없어요… Playwright 웹브라우저가 돌아가기위해선 디펜던시가 필요했고, 위에얘기한 설치명령어를 통해서 설치할 수 있더군요.
아니, 웹브라우저가, 바이너리만 있으면 되야하는거 아니냐고요. 왜 이걸 설치해야하는데요? 하, 이걸 포함안시켜놨네…
플레이라이트는 크로미움,웹킷, 파이어폭스 웨브라우저를 사용가능하고 각각 따로 설치되던데요.시스템 디펜던시도 웹브라우저마다 다릅니다. 물론 플랫폼별로도 다르죠. macOS용과 리눅스용은 따로겠죠.
결국 디펜던시를 설치해야하니 저 위에 바이너리를 포함해서 배포하겠다는 제 계획은 괜한 뻘짓이 되었고 (해봐야 어차피 설치과정을 거쳐야하니…) CDN주소 없이 직접 바이너리 빌드한 삽질이 떠올라 잠을 못 잤어요.
설치할 목록이 꽤 많았어요.마찬가지로 앞전에 얘기한 스크립트파일로 설치하는데요. 이 리눅스 설치명령어를 리눅스에서의 경우,apt-get으로 박아뒀더군요.
apt-get은 데비안 계열 리눅스의 패키지매니저이고… yum을쓰는 레드헷계열 CentOS나 아마존리눅스에서는 저 스크립트가 안먹는거에요. 하!
처음에 저는 그것도 모르고 CentOS랑 아마존리눅스2와 2023에서 했거든요! 웹브라우저 설치 원리를 알기전에 말예요!
하지만, 일말의 희망으로 아마존 리눅스에 디펜던시 목록을 보고 직접 하나하나 설치해보기로 합니다 (괜한 고집).
결론은 아마존리눅스2에서는 불가능했고 2023버전에서는 크로미움용 디펜던시만 설치 가능했어요.
아마존리눅스 2나 CentOS나 다른 브라우저는 디펜던시 설치과정에 에러를 뿜었는데 chatGPT에게 물었더니 이런 에러는 리눅스 해당버전 근간을 흔드는 라이브러리를 바꿔야한다고 chatGPT가 저에게 겁을 줬습니다. 그냥 다른 배포판 쓰라대요.
저야 암것도 모르고 삽질한거지만 Playwright 문서상으로 공식적으로 박아뒀네요. “only support Ubuntu”. 아니 왜….
후에 아마존리눅스에서 개삽질 실패하고 생각하게된거지만 MS가 일부러 AWS에서 못쓰게할려고 그랬을거예요. AWS 람다는 아마존리눅스에서 돌거든요.
도커 컨테이너를 배포하자
이유는 당연히 AWS 람다에서 돌리기 위해서였어요.
일단 SDK나 닷넷런타임설치없이는 통과했지만 결국 웹브라우저가 필요하고 그마져도 설치과정이 필요하니, 도커이미지는 필수였죠.
이것은 물론, 우분투만 되는 저 내용을 알아내기 이전이었습니다. MS 나빠요 흙흙흙.
개인적으로 도커는 이제까지 개념만 알고 있었지 쓸일이 없었어요. 이번기회에 다시 공부했습니다.
도커파일 작성 방법을 공부하려니 또 짜증나대요?
아실분은 아시겠지만 node.js나 파이썬같은 스크립트언어는 컴파일이 없고 개발환경자체가 배포환경이죠.
그런데 닷넷은 컴파일을 하고 배포해서 나오는 배포파일을 써야하죠.
앞서 얘기햇듯 (고집부렸듯) 배포환경에 SDK설치하기 싫었어요. 도커이미지 만드는데도 그걸 넣을 이유가 없었죠.
그때문에 도커파일 작성당시 멀티스테이지빌드를 해야했어요.
근데 도커파일을 처음작성해보는데 제가 아나요? 안그래도 없는 닷넷코어 정보인데
도커에서 Playwright 웹브라우저와 디펜던시 설치? 닷넷코어로 이러는경우는 또 거의 없어요. “이짓하는게 나 뿐인가?”하는 생각이 들더군요.
chatGPT한테 물어물어서 도커파일작성도하고 결국 컨테이너 실행하니 데모앱 잘 돌아가더군요?
“와 이제 다 됐다. 데모앱말고 진짜앱 코딩해도 되겠다. 지겨운 개발환경 그만꾸미고 그만 코딩하면 되는거야!”
라고 생각했지만 좀 불안하더군요.
“나는 얼마나 많은 삽질을하면서 여기까지 왔던가…”
AWS 람다에까지 올려봐야겠더라고요. AWS ECR에 도커컨테이너를 올리고 거기서 실행하니 잘 되더군요.
완벽한 테스트를 위해 B단이 필요하니 로컬에 MAMP로 워드프레스 설치하고 플러그으로 API만들고, 공유기 까서 포트포워딩으로 외부IP접속 열고 ECR 컨테이너를 실행하니 파일이 잘 받아졌어요.
ECR에있는 이미지로 람다 함수를 만들면 그만인거라고 생각했죠. 도커잖아요? 무슨 문제가 있겠어요? 물론, Playwright가 ubuntu만 지원되고 (저는 우분투 이미지를 만들었고) 람다는 아마존리눅스라는 사실을 몰랐때 얘기였죠.
AWS 람다는 우분투가 아닙니다.
테스트를 아무리 돌려도 에러만 뿜뿜.
커스텀 리눅스로 돌리려면 뭔가해야한다는 실마리만 얻고 능력부족+지침으로 못했습니다. 론칭이 코앞인 상황에 그냥 빨리 끝내고 싶더군요.
아, 근데 서버비용없이 돌려야하는데..라는 생각으로 MS Azure Function으로 눈을 돌렸어요. 이건 우분투라네요. (MS 너, 일부러 그랬지?)
그래서 Azure 서비스를 이것저것 알아봤어요. 애저펑션도 매월 무료사용량을 주긴하지만 문제는 도커컨테이너를 저장할 곳이었어요. AWS ECR처럼 Azure에도 컨테이너 저장소를 쓰려했는데 이건 무료사용량을 안주네요;
얼마 안되는 가격이었지만 이짓하는 이유가 무료로 돌릴 가능성 때문인데요.
그래서 다른 서비스를 알아보는데 컨테이너앱스 란게 있더군요. 한달 18만초(이틀) 무료.
이걸 잠깐잠깐 껐다켜면 무료사용이 가능하단 계산이 나왔어요.
그런데. 그 스케줄을 실행하는 다른 서비스가 비쌌어요 ㅎㅎㅎㅎ 야이!
용량문제
애저서비스와 AWS서비스들을 둘러보며 생각을 거듭하다 AWS ECR에 올려두고 Azure Functions에서 돌리는걸 생각하게되더군요. 그런데 매번 실행될때마다 이미지를다운받아야하니 번거로워보였어요. ECR이 5테라까지 전송무료긴한데요.
AWS -> Azure 로 하루 몇번씩 1.2기가 컨테이너를 전송한다는게 탐탁치 않더군요.
Playwirght 는 Node.js를 포함하고 있어서였는지 용량이 컸습니다(잘모름). 웹브라우저 여럿쓸수는 있지만 바이너리가 각각 4~500mb이기도합니다. 3종 설치하면 그것만 1.5기가죠. 그나마 최소치만해서 1.2기가 이미지가 나온것이죠.
개발환경을 포함시키려하지 않으려던 제 고집과 노력(?)이 없었다면? node.js도 설치하고 닷넷SDK도 설치하고… 도커이미지 용량이 산으로 갔겠죠
공짜좋아하다 머리 벗겨진다
그냥 생각끝에 A서버를 쓰기로 했습니다. 마침 다른 거의 놀고있는, 버릴까말까하다가 그냥두고있는 워드프레스 서버이기도했고 말이죠.(그런 서버가 있으면 그냥 쓰면되지 여태 왜 고집을 피운거야?)
결국 AWS람다로 어떻게 무료로 돌려볼까하는 생각이 저 많은 삽질중 상당수를 차지하며 제 머리카락을 한웅큼 뺏어간거죠.
전 그냥 잘해보려고한 것뿐인데 억울합니다.
결론
Playwright 하려면 node.js 로 개발하세요.