카테고리 없음

241119 배운점

hanseongjun 2024. 11. 20. 04:28
728x90
반응형

project 링크

https://github.com/fclipse/namdo-haksuk-notice

배운점들

1. python crawler 사용법

이 부분은 BeautifulSoup 라이브러리를 사용하여 HTML 문서에서 특정 요소들을 선택하는 코드입니다. 이 코드는 div 태그 중 클래스가 board-list-wrap인 요소 내의 tbody 태그 안에 있는 모든 tr 태그들을 선택합니다.

클래스와 ID 선택자를 BeautifulSoup에서 사용하려면 CSS 선택자를 사용하면 됩니다. 예를 들어, 클래스 선택자는 .을 사용하고, ID 선택자는 #을 사용합니다.

예시:

  1. 클래스 선택자 사용:
# 클래스가 'example-class'인 모든 요소 선택
elements = soup.select('.example-class')
  1. ID 선택자 사용:
  2. # ID가 'example-id'인 요소 선택 element = soup.select('#example-id')
  3. 클래스와 ID를 함께 사용:
  4. # 클래스가 'example-class'이고 ID가 'example-id'인 요소 선택 element = soup.select('.example-class#example-id')

적용 예시:

# 클래스가 'board-list-wrap'인 div 내의 tbody 안에 있는 모든 tr 태그 선택
notice_list = soup.select('div.board-list-wrap tbody tr')

# 클래스가 'example-class'인 모든 요소 선택
example_class_elements = soup.select('.example-class')

# ID가 'example-id'인 요소 선택
example_id_element = soup.select('#example-id')

# 클래스가 'example-class'이고 ID가 'example-id'인 요소 선택
example_class_id_element = soup.select('.example-class#example-id')

이렇게 하면 BeautifulSoup을 사용하여 HTML 문서에서 특정 클래스나 ID를 가진 요소들을 선택할 수 있습니다.

2. python에서 .env파일 변수를 안전하게 불러오는 패턴

DEBUG = os.getenv("DEBUG", "False").lower() in ("true", "1", "t")

이렇게 하면 .env에 DEBUG 변수가 없으면 기본적으로 False값을, True / true / 1 / t 중 하나라도 있으면 True값을 DEBUG 변수에 저장하게 된다.
DEBUG 변수가 bool type 임을 보장해주는데, 정말 식이 간결하게 쓰여진 것 같다.

3. discord 봇 사용법

https://cjwoov.tistory.com/104
해당 블로그를 많이 참고했다.
만약 봇이 작동이 잘 안되면

  1. 채널 id 확인
  2. bot previlliged 권한 확인
  3. oauth2 page에서 bot 권한 확인
    을 하자.
    나는 잘 안돼서 그냥 3.에서 bot한테 admin 권한을 줬다.

디버깅 내용

  1. .env 안바뀌는 문제
  • 상황: venv 실행중
  • 문제: .env파일의 내용을 바꿔도 python을 실행하면 바뀌지 않은 채로 실행됨
  • 해결: venv를 종료 -> .env 수정 -> 다시 venv접속 후 실행 -> 해결;;;;

venv를 킨 상태에서 .env를 바꾸면 바로 반영이 안 되는 것 같다.
왜 이러는진 모르겠지만(.venv로 이름을 설정하니까 vscode venv 가 자동실행됨. 이것 때문인가)
.env를 수정했다면 terminal을 종료하고 다시 켜서 앱을 실행하자.

  1. docker 이미지 관련 문제
  • docker 이미지 빌드시 apt-get 못 찾는 문제

-> claude 답변

이 에러는 Docker 이미지 빌드 중 Nginx 설치 과정에서 발생한 문제입니다. 주요 원인은 다음과 같습니다:

nginx.conf 파일 충돌

CopyConfiguration file '/etc/nginx/nginx.conf'
==> File on system created by you or by a script.
==> File also in package provided by package maintainer.

이미 nginx.conf 파일이 존재하는데 새로운 설치가 시도되어 충돌이 발생


해결 방법은 Dockerfile을 다음과 같이 수정하면 됩니다:

dockerfileCopy# Nginx 설치 전에 기존 nginx.conf 제거
RUN apt-get update && \
    DEBIAN_FRONTEND=noninteractive apt-get install -y nginx && \
    rm -f /etc/nginx/nginx.conf

# 그 후 nginx.conf 복사
COPY nginx.conf /etc/nginx/nginx.conf
주요 변경사항:

DEBIAN_FRONTEND=noninteractive 추가: 설치 중 대화형 프롬프트 방지
nginx.conf 파일을 먼저 제거하고 나중에 복사
각 명령어를 &&로 연결하여 레이어 수 최소화

이렇게 수정하면 nginx 설치 과정에서 발생하는 설정 파일 충돌 문제를 해결할 수 있습니다.
# Nginx 설치 및 설정
RUN apt-get update && \
    DEBIAN_FRONTEND=noninteractive apt-get install -y nginx && \
    rm -f /etc/nginx/nginx.conf
  1. start.sh 못 찾는 문제
    다음 링크 참고

https://kkkkang1009.tistory.com/entry/docker-error-start-not-found

  1. uvicorn run 관련
    https://jandari91.github.io/posts/fastapi_start/
  • python main.py 하고 name == 'main' 밑에 uvicorn.run() 적는거랑 cmd에 uvicorn main:app ~~ 적는거랑 같음!!
  1. nginx conf 관련
    ```
  2. proxy_pass http://127.0.0.1:8001; 여긴 localhost가 들어가야 한다.
    ```
  3. port 관련
    docker -> nginx -> python app 이렇게 3개의 앱이 실행되는데, 이때 사용되는 포트는 총 3가지이다.
    1) docker host port - 외부에서 실행 중인 docker 이미지에 접근할 때 쓰이는 포트 / docker run 시 설정된다. 5000:8000 이라면 앞이 host port, 뒤가 container port
    2) container port - docker 이미지 내부 포트 / docker run시 설정하고, nginx conf에서 같이 설정해줘야 한다.
    3) python app port - python app이 docker image 내에서 돌아갈 때 쓰이는 포트, nginx conf에 설정되며 python app 내 uvicorn.run() or uvicorn main:app 등의 명령어 에서 설정된다. 마찬가지로 같게 맞춰줘야 한다.
  4. fastapi 비동기 처리 관련
    이번 프로젝트에서 까다로웠던 점은 다음과 같다.
    먼저 discord_bot.py, web_ui.py, scrape.py가 모두 따로따로 노는데 이를 모두 비동기처리로 처리해야 한다.
    그리고, discord_bot.py가 실행된 후에 (bot이 준비된 후에) scrapping이 실행되어야 한다.

이 조건을 만족하기 위해선 모두 다 async.gather()에 집어넣어 돌리거나, 각각을 await처리해주는 게 아닌, 따로 함수를 만들고 그 안에서 조건을 걸어 실행해줘야 한다.
나는 다음과 같이 설정해줬다.

async def start_bot():
        await bot.start(Config.DISCORD_TOKEN)

 async def run_tasks():
        # bot이 준비될 때까지 대기 - 그 이전에 공지사항을 확인해버리면 봇이 준비되기 전에 메시지를 보내게 됨
        await bot.wait_until_ready()
        await check_notices()

 config = uvicorn.Config(app, host="0.0.0.0", port=8001, log_level="info", reload=RELOAD)
 server = uvicorn.Server(config)

 await asyncio.gather(
        start_bot(),
        server.serve(),
        run_tasks()
    )

이렇게 하면 start_bot, 서버, run_tasks가 모두 동시에 실행되는데, run_tasks() 안에 chekc_notices는 await이 걸려 있어 bot이 준비되기 전까지 실행되지 않는다.

후기

비동기 처리가 왜 어렵다고 하는지 알 수 있었다.

그리고 생각보다 docker image 및 python run 설정에 시간이 많이 소요했다. (3~4시간)
나중에 기업용 소프트웨어는 더 복잡한 구조의 애플리케이션을 돌려야 할 건데, 그 돌아가는 순서에도 정말 복잡한 과정이 있음을 간접적으로 느꼈다.
그리고 왜 devops 엔지니어를 따로 두는지 알 수 있었다.

+ uvicorn.run()이랑 uvicorn main:app 이것때문에 얼마나 시간을 잡아먹은건지..

아 맞다, 그리고 vscode에서 copilot으론 gpt 대신 claude를 이용하자... 성능 차이가...

그리고 명심하자. AI는 아직 완벽하지 않다.

자동화 하나 만드는 과정에서도 아직까지 상당히 오류나 버그가 많았다. 다행히 아직까진 대체되지 않을 수 있을 것 같다는 느낌을 받았다.

728x90
반응형
LIST