Week 44(1028-1101)241101(Fri)Week45(1104-1110)241104(Mon)241105(Tue)241106(Wed)241107(Thu)241108(Fri)241109(Sat)241110(Sun)Week46(1111-1117)241111(Mon)241112(Tue)241113(Wed)241114(Thu)241115(Fri)241116(Sat)241117(Sun)Week47(1118-1124)241118(Mon)241120(Wed)241121(Thu)241122(Fri)241123(Sat)241124(Sun)Week48(1118-1124)241125(Mon)241126(Tue)241127(Wed)241128(Thu)241129(Fri)241130(Sat)241201(Sun)
Week 44(1028-1101)
241101(Fri)
- 장고 로그와 CloudWatch 관련 공부
- 다소 비용이 비싸다는 느낌. S3에 비교하면. 저장용보다는 말그대로 로그에 최적화된 기능. 저장 기간도 1개월이 기본이니
- mypy 사용해보기
- 파이썬 객체지향 책을 읽으며 알게 되었는데, 괜찮은 느낌. 몇개의 오류 발생 가능 지점을 발견했음.
- 크롤링 관련
- 인증을 요하는 크롤링시 csrf 토큰 처리해보기
- 장고 앱에서는 헤더의 쿠키 그리고 폼에
csrfmiddlewaretoken
를 요구한다. - referrer 설정도 필요하다는 말이 있는데, 이건 안해도 가능했음.
- 기존 추상화된 코드에 대한 고민
- 인증 코드에서 세션인증/토큰인증등에 따라서 분리하고 재사용이 용이하게 구현을 했었다.
- 그러나 실제 사용했을 때 세션-csrf-장고폼-인증 이런식으로 실제 인증 문제는 복잡하고 구체화 된 구현이 필요했음.
- 각각 과정을 나누어 템플릿 메서드 패턴등을 사용해보아도 되겠지만, 억지 추상화라는 느낌이 들었다. 결국 인증도 개별 도메인에 종속된 경우가 많았음.
- 그래서 차라리 개별 도메인별 ~Auth 클래스를 만들고, 디비에서 single table 전략으로 구성된 테이블에서 나온 객체를 기반으로 팩토리? 패턴으로 ~Auth 객체를 가져올 수 있게 해서 DB와의 연동을 편하게 하자고 생각했다.
- 기존의 파일 구조도 Auth, Fetcher 등으로 나누었는데, 도메인별로 파일을 분리하기로 수정. 차라리 도메인별로 응집도를 높이는게 좋다고 느껴졌다.
Week45(1104-1110)
241104(Mon)
- 장고 개발
- single table 전략을 이용해 복잡한 요구 사항 구현하기
- 실제 구현과 기존 예상의 괴리가 있어 추상화 줄이기
- 로깅 설정
- 로거와 핸들러중 우선 로거에서 로그를 수집
- 이때 앱 이름이 포함되어야 함. django는 장고 자체 로그들
- 아니면 loggers 하위에 앱이름 대신 그냥 loggers 레벨에 root라는 이름으로 만들면 전체 적용됨.
- 로거에 핸들러 이름을 설정에서 이걸 핸들러로 보냄
- 핸들러는 이걸 받음. 이때 로거와 핸들러 둘다 level설정이 있는데, 높은게 적용. 즉 로거에서 한번 거르고 핸들러에서 한번 거르는 용도임.
- 핸들러에서는 필터와 포매터 적용 가능
- 테스트 코드 작성, MagicMock을 써보았다
- 객체 지향적 코드를 짜야하는건 테스트를 위함이 아닐까… 하는 생각. Spring DI가 이런건 편했는데
241105(Tue)
- 솔리드 커넥션 웹 개발
- App Router 전환
- 일단 먼저 use client 대부분 적용해 react와 다름없는 수준으로 마이그레이션하고
- 바뀐 useRouter등만 우선 전환해주기
- 어짜피 인증이 필요한 페이지가 많아 ssr 적용할 곳이 크게 많지는 않음. 급한것도 아니고
- 우선 빨리 전환하고 네이밍도 바꾸고 리팩토링하는게 우선으로 보임
- 장고 개발
- difflib.SequenceMatcher, get_close_matches를 사용해 이름 오타시에도 자연스럽게 진행되게 하는 기능 추가
- ruff 린터 사용해보기
- mptt라는 모델 트리구조 라이브러리를 알게 됨
- 어드민 페이지 검색 필드등 커스터마이징 할 수 있는 것을 알게 됨
241106(Wed)
- 솔리드 커넥션 웹 개발
- 메인 화면 App Router 전환
- 폰트 최적화
241107(Thu)
- 솔리드 커넥션 웹 개발
- App router 이전 작업
- Lint 오류 수정
241108(Fri)
- 장고 기존 코드 수정 작업
- 문제: dbeaver로 데이터 덤프딸때 초기 부분과 insert 부분 sql이 잘리는 문제
- dbeaver 실행 명령어 그대로 실행했을 때는 괜찮은거보니 dbeaver 버그인듯. 메모리 문제일지도
- 문제: 장고 db_comment해도 특정 필드는 적용이 안되는 문제
- 안되는 필드는 그냥 DB에 직접 적용해주는걸로…
- 이전 버전과 신규 버전 동일 api 동일 response 체크
- 대부분 수작업으로 했는데, 자동화 될듯. 이미 솔루션도 많을지도
241109(Sat)
- 솔리드 커넥션 서버 DB 이전
241110(Sun)
Week46(1111-1117)
241111(Mon)
- 인턴십: 내부망에 DB 마이그레이션, 서버 코드 변경 작업
241112(Tue)
241113(Wed)
- 솔리드 커넥션 서버 인증서 갱신
- standalone 방식은 nginx 관련 문제인지 안되서 dns 레코드 변경 방식으로 성공
- 컨테이너 레지스트리 비교 글 작성
- 인턴십: nginx 리버시 프록시 이용해 한 서버에서 프론트/백엔드 동시 배포 작업
- 그냥 내부 포트 8001번으로 열고 8000에서 프록시
241114(Thu)
- ACC Inha 발표: 메시지 큐와 SQS
241115(Fri)
- 인턴십: 데이터 수집 celery task, command 작성 작업
241116(Sat)
241117(Sun)
Week47(1118-1124)
241118(Mon)
- 인턴십: api 개발, 테스트코드 작성
- selector 레이어 사용, 중복 쿼리 일부 통합해서 최적화
- 일단 1차 배포~
241120(Wed)
- 인턴십
- swagger 오류 수정 → 요청하는 url의 포트 문제. 임의 지정해줌
- sql 쿼리 최적화
- 프론트엔드 api endpoint 연결작업
241121(Thu)
- 솔리드 커넥션 웹 개발
- 버그 해결. 빌드가 vercel에서만 안되는 문제
- tab.tsx → Tab.tsx로 이름 변경했는데 git에서 못잡아서 반영이 안됨. 그리고 import만 바뀌어서 모듈을 못찾는 문제였음
- 이를 해결하기 위해
git config core.ignorecase false
- JS 병렬 fetch
Promise.allSettled()
Promise.all()
는 요청중 하나라도 오류가 발생하면 모두 오류가 발생한다- 즉 서로 연관된 작업을 수행하기에 좋음
Promise.allSettled()
는 서로의 성공여부에 관계 없이 비동기 작업을 수행한다
- 스프링 빈 스코프
- 스코프: 빈이 존재할 수 있는 범위
- 종류
- 싱글톤: 스프링 컨테이너의 시작 ~ 끝 까지
- 프로토타입: 스프링 컨테이너는 생성, DI만 해주고 더이상 관리 x
- 즉 이후 관리 책임이 없어
@PreDestroy
호출되지 않음 - 웹 관련 request, session, application(웹의 서블릿 컨텍스트와 같은 범위)등
- 활용법: 로거등에 사용해서 웹 요청 시작 ~ 끝을 명확히 보이는데 사용 가능
- 사용법: 빈 클래스 위에
@Scope(”prototype”)
로 자동 스캔
- 싱글톤 빈 안의 프로토타입 빈
- 싱글톤 빈 내에서 프로토타입 빈을 사용할때 해당 빈은 싱글톤 빈이 주입받을 때 생성된 것으로, 매번 다시 생성되지 않는다. 이에 주의
- 그렇다면 매번 새롭게 생성하려면 어떻게 해야할까?
ApplicationContext ac
,ac.getBean()
을 사용하면 프로토타입 빈은 매번 새로 생성됨- 이렇게 DI를 받는게 아닌 직접 찾는걸 DL(Dependency Lookup)이라고 함
- 문제는 이러면 스프링 컨테이너에 종속적인 코드가 된다
- 그래서 다음 기술을 사용할 수도 있음
ObjectProvider<PrototypeBean> prototypeBeanProvider
prototypeBeanProvider.getObject()
- 이것도 스프링에 의존적
- 아니면
javax.inject.Provider
라는 자바 표준을 사용할 수도 있다 - 느낀점: 이걸 쓸일이 과연 있을까? 억지로 mq를 써보는 느낌
- 스프링 프록시
- SQS at-least-once 보장에 대한 생각
- https://channel.io/ko/blog/articles/1d129345
- 이러한 구조에서 메시지가 중복될 수는 있어도 유실될 수는 없다
- 여기서 중복을 막기 위해서는
- 멱등성. 즉 여러번 처리해도 괜찮게 설계
- 외에는 사실 어려운 느낌. 필터를 둔다던가…
- 2PC?
- Inha ACC 발표 듣기
- Serverless
- CI/CD 핸즈온
- 인턴십
- 프론트엔드 api 연결 작업
- same-site same-origin cors csrf 이것저것 많은 고민
- 코드 리팩토링, 테스트 작성
241122(Fri)
- Postman alternative
- Postman
- brew monthly 11.3k downloaded
- Insomnia
- brew monthly 2.2k downloaded
- Pricing
- Hobby: Unlimited collaborators for 1 project
- Pro(12$/M)
- Hoppscotch
- 브라우저에서 사용 가능
- brew monthly 0.3k downloaded
- soapUI
- brew monthly 0.2k downloaded
- 인턴십
- cors, csrf 관련 문제 모두 해결. 할 수 있는것과 불가능것을 완전히 이해했다.
- ImageField에 image.url 줘서 안되는 문제 수정… image를 줘야한다
- react 로그인 상태에 따른 서비스 진입/로그인 화면 분기 처리
- Influx DB 공부
241123(Sat)
241124(Sun)
Week48(1118-1124)
241125(Mon)
- Celery 실패한 task 재시도 방법 고민
- 동적 배열 크기 증가할때 2배씩 증가하는게 가장 효율적이라는 걸 본 기억으로 2배씩 증가할까 고민
- 찾아본 결과 이를 Exponential Backoff 라 하고, Celery 5부터 아에 쉽게 사용할 수 있도록 지원한다는 것을 알게됨
- 그리고 Jitter에 대해서도 알게 되었다. 이것도 한번에 open api서버에 요청할때 밴될까봐 고민했던 사항인데 AWS 블로그를 보고 효율적인 jitter 전략등을 알게 되었다.
- 아무튼 구현하려 보니 task가 date 의존적이라 인자를 첫번째 시도의 것을 계속 가져가야 해서 Celery에서 편하게 사용할 수 있게 해둔것은 못쓰고, 자체 구현해서 사용했다.
- Celery에서의 Exponential Backoff and Jitter 글 작성 시작
- 장고 블루 그린 무중단 배포 구현
- 겪은 많은 오류들… 대부분 gpt에 대한 과한 신뢰에서 나왔다
- The workflow is not valid. .github/workflows/cd-prod.yml (Line: 79, Col: 13): A mapping was not expected
# ssh-action에서 ENV 지정을 다음 처럼해서 발생 - name: Deploy via SSH uses: appleboy/ssh-action@v0.1.5 with: env: REGISTRY: ${{ needs.build-and-push.outputs.REGISTRY }} REPOSITORY: ${{ secrets.ECR_REPOSITORY }} AWS_REGION: ${{ vars.AWS_REGION }} IMAGE_TAG: ${{ github.sha }} # 다른 방법이 있는진 몰라도, 공식문서상으론 다음처럼 예시가 되어있다 - name: Deploy via SSH uses: appleboy/ssh-action@v0.1.5 env: REGISTRY: ${{ needs.build-and-push.outputs.REGISTRY }} REPOSITORY: ${{ secrets.ECR_REPOSITORY }} AWS_REGION: ${{ vars.AWS_REGION }} IMAGE_TAG: ${{ github.sha }} with: envs: REGISTRY, REPOSITORY, AWS_REGION, IMAGE_TAG
source: | ./docker-compose.yml ./deploy/nginx.conf.template ./deploy/deploy.sh
error copy file to dest: ***, error message: ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey], no supported methods remain
- gpt가 계속 scp-action@v0.1.1을 고집했는데 v0.1.7로 바꿔주니 해결됨. latest stable 버전을 쓰자고 고집하더니… o1-preview라 믿었는데 그냥 최신 정보 업데이트가 안된건지…
- chmod +x 추가해줬다
err: Unable to locate credentials. You can configure credentials by running "aws configure". err: Error: Cannot perform an interactive login from a non TTY device
241126(Tue)
- 엑셀 파싱 코드 작성중, 오류가 발생
- 엑셀파일 raw로 열어보니 오히려 html의 구조를 가진것을 보고 pandas read_html로 해결했다
- S3를 안쓰고 파일 저장, 인가에 대한 고민
- 장고에서 파일을 저장하고 다운로드 가능하게 해야하는데, S3는 못쓰고 nginx등으로 직접 서빙해야한다
- s3에서는 잠깐만 접속 가능한 링크를 발급하는 방식이 있는걸로 아는데
- 일단 찾아보니 nginx에 헤더를 바탕으로 인증 처리할 수 있는게 있다고 한다
- 다만 생각해보니 인가가 필요하긴 하나 매우매우 엄격해야 하는 것은 아니고, url을 복잡하게 하는것 만으로 보안을 어느정도 지킬 수 있다고 생각이 되었다
- 굳이 따지면 s3에서 임시 링크등을 발급받아도 잠깐동안은 누구나 접근 가능하지만, url을 쉽게 추측할 수 없는게 핵심이니깐
- 그래서 uuid를 이용해서 해결 했다
- uuid 버전은 목적상 완전 랜덤이 맞다고 보아 uuid4로 적용. timestamp등은 오히려 노출되면 안된다고 보았다.
241127(Wed)
- 엑셀 → fastapi → influxdb로 시계열 데이터 저장하는 것 구현
- influxdb flux의 사용은 다소 어려웠다. 일반 field와 key의 차이를 크게 느꼈다
- influxdb는 그래도 자체 대시보드가 있어서 좋은듯
241128(Thu)
- googlemaps/google-maps-services-python 를 참고하여 라이브러리를 만들어 보기로 했다
- 데이터 보정 코드 구현하며 pandas의 melt()를 알게되었는데 신기한 느낌. 이런 데이터 라이브러리에는 자동으로 중간에 비어있는 값을 넣어주는 그런 함수도 있다는데 재밌는 것 같다.
241129(Fri)
- 일본 리전 rds가 접속이 안되는 문제
- 문제상황을 듣고 대충 VPC나 WAF문제가 아닐까 생각
- 일단 회사 네트워크 문제일 수 있으니(학교에서는 MySQL 포트가 막혀있는 경우가 있었다. 일본 IP가 막혀있거나 일본쪽에서 막고 있을 가능성도) 직접 파서 확인. 이상이 없었다
- 특이점으로는 한국 rds는 핑 200ms대인데 일본은 1600ms로 확실히 차이가 났다
- 커넥션 뚫는거라 느린 것 일수도? 커넥션 뚫어둔 후 일반 DB 쿼리는 이것보단 빠를거라 생각한다
- 일단 계획으로는 VPC Flow Logs로 로그를 확인하거나
- 정 안되면 EC2에서는 연결 되니 mysql_fdw 등으로 프록시를 만드는 것
- 문제 해결을 위해 실제로 해보니 그냥 됐다… 뭔가 설정 문제가 있었던걸지도… 약간 허무한 결말