Week 40(0930-1006)241001(Wed)241002(Thu)241003(Fri)241005(Sat)241006(Sun)Week 41(1007-1013)241007(Mon)241008(Tue)241009(Wed)241010(Thu)241011(Fri)241012(Sat)241013(Sun)Week 42(1014-1020)241014(Mon)241015(Tue)241016(Wed)241017(Thu)241018(Fri)241019(Sat)241020(Sun)Week 43(1021-1027)241021(Mon)241022(Tue)241023(Wed)241024(Thu)241025(Fri)241026(Sat)241027(Sun)Week 44(1028-1101)241028(Mon)241029(Tue)241030(Wed)241031(Thu)
Week 40(0930-1006)
241001(Wed)
- 공부
- React Suspense, Lazy
241002(Thu)
241003(Fri)
241005(Sat)
- 솔리드 커넥션 웹 개발
- App Router 전환중
241006(Sun)
Week 41(1007-1013)
241007(Mon)
- 솔리드 커넥션
- 데이터 추가
- 서버 배포, 오류 해결
- DRF 테스트 코드에서 json 리턴에서 나올 수 없는 decimal 타입이 나오는 것을 확인
- DRF 테스트에서 res.data는 완전 외부 테스트 느낌이 아닌 어느정도 의존성이 있다는 것을 확인
- 그나마 줄이려면 res.content를 직접 json 변환해도 될듯
- 아니면 request 기반의 APIClient도 있는 것 같다
- 그리고 204 status code일때 body를 검증해주지 못하는 문제?
- 이것은 원래 204일때는 body를 포함한것을 상정하지 않아서 그런듯. HTTP 표준은 아니지만… GET 요청에 body 없는것도 표준은 아니니
- 이걸 해결하려면 res.data로 response body를 직접 다시 검증해줘야 하는것이 일단 대안
- 장고 프록시 모델과 django-lifecycle 관련 강의 수강
241008(Tue)
- MySQL 필드 타입 학습
- 괜찮은 치트시트: https://spiderwebcoding.tistory.com/5
- 솔리드 커넥션 기능 수정 DB 고안
- FastAPI 학습
- 세션 관련 학습
- ERD 그려보며 DB 설계
241009(Wed)
- 솔리드 커넥션 웹 개발
241010(Thu)
- 솔리드 커넥션 웹 개발
- 기존 공통 컴포넌트 리팩토링
- 미식록 서버 개발
- 데이터 수정
241011(Fri)
- FastAPI 학습
- mqtt 학습
- QoS
- Clean session
- Gmap Tiles API 관련 코드 리팩토링
241012(Sat)
- Topcit 시험
- 복기
- SQL 권한 주기 GRANT TO 회수는 REVOKE FROM
- VARCHAR2: 오라클에서 쓰는 개선판 VARCHAR
- 테이블 필드 추가: alter table 테이블 add 컬럼 varchar(100) not null
241013(Sun)
Week 42(1014-1020)
241014(Mon)
- Gmap Tiles 를 이용한 지도 생성
241015(Tue)
- react-router-dom
- <RouterProvider />, createBrowserRouter()
- path, element, errorElement
- <Outlet />
- <Link />
- dynamic segment
- styled-component
241016(Wed)
- MySQL 트랜잭션 격리수준
- READ UNCOMMITED
- 커밋되지 않은 값도 읽을 수 있음
- Dirty read: 트랜잭션이 완료되지 않아도 다른 트랜잭션에서 확인할 수 있는 현상
- 즉 롤백했는데 유효한 데이터라 착각 할 수 있다
- READ COMMITED(대부분 기본 트랜잭션 격리 레벨)
- 커밋전에는 Undo table의 값을 읽어오기에 커밋이 완료된 값만 읽을 수 있음
- Non repeatable read: 같은 트랜잭션 내에서 값을 두번 읽을 때 서로 다른 값이 들어올 수 있다
- REPEATABLE READ(기본 트랜잭션 격리 레벨?)
- MySQL에서는 트랜잭션이 생성된 순서로 번호를 부여한다
- 이런 동일한 레코드에 대해 여러 버전이 존재하는 관리 방식을 MVCC(Multi Version Concurrency Control)이라 한다.
- SERIALIZABLE
- SELECT FOR SHARE/UPDATE가 아닌 순수한 SELECT(Non-locking consistent read) 작업시에도 공유락(다른 트랜잭션에서 읽기 가능, 수정 불가능)을 설정한다
- 그렇기에 가장 안전하지만, 가장 성능이 떨어진다.
- 미식록 서버 버그 수정
- 데이터 양이 늘어남에 따라 어드민 페이지에서 로딩이 느려지는 문제
- 다만, SQL자체는 빨리 끝나나 CPU time이 매우 높게 잡힘
- 관련된 리소스 전체 목록을 보여주는게 아닌, raw_id_fields를 적용하여 해결
- 3000ms → 200ms
- 엑셀 → 파이썬 변환
- openpyxl 보다는 pandas를 바로 쓰는게 편한듯
- 장고 프로젝트 DB 설계
241017(Thu)
- 장고 커스텀 유저 모델 설계
- API 개발
241018(Fri)
- svg 구조 학습
- API 개발
- 개발하며 느낀점. 서비스 로직이 있는게 아닌 조회라면, 조금 복잡한 조회라도 최대한 DRF generics를 쓰는게 좋은듯
- serializerMethodField를 쓰더라도 차라리 로직을 그쪽에 넣어두는게 좋은 느낌
- 좀 복잡하더라도 related 된걸 좀 가져오거나, 어느정도 계산을 할 뿐이니
241019(Sat)
241020(Sun)
- 미식록 데이터 추가
Week 43(1021-1027)
241021(Mon)
- 장고 개발
- 깔끔한 조회 api 코드 작성하기
- svg로 지도에 마커 추가, 마커 클러스터링
- 클러스터링: 주변 마커 탐색 알고리즘과, 좌표 기반 방식으로
241022(Tue)
- 장고 개발
- test 코드에서 unittest.mock patch 사용해보기
- 파이썬 린팅 관련
- isort 추가, black formatter 규칙 추가
- swagger 적용
- 장고 모델 제약조건 관련 학습
- 4가지의 검증 단계가 있고 full_clean()으로 모두 실행 가능
- 이중 모델 Meta에 추가한 constraint만 DB 제약으로 들어가고 나머지는 모두 Django 어플리케이션단 검증
- 모델 설계
241023(Wed)
- 장고 개발
- API 개발, Subquery, OuterRef와 annotate를 이용해 n+1 문제 방지
- 장고 고급 쿼리문 작성 관련 학습
- 신기했던 점: 이런 Q, F, Sum, Subquery등 어떻게 구현했는지 신기했던 것을 내부적으로 보니 각 객체에 정의된 template의 규칙에 따라 그냥 작동하고 있었 다는 것
241024(Thu)
- 미식록 서버 개발
- 프랜차이즈 추가, 프랜차이즈 메뉴 - 식당 메뉴 연결
- 장고 개발
- API 파싱/데이터 크롤링 코드 작성
- 다양한 서비스에 대응 가능하게 추상적으로 작성
- 인터페이스, 인증에서는 전략 패턴을 사용해서 재활용이 용이하게 작성
- 응집도를 고려한 설계
- 정해진 API 파싱 코드 작성
- 변경이 적은 API에 미래에도 사용할 수 있게, TypeDict를 이용해 반환값 정리
- API 공통 부분을 통합하여 사용하게 쉽게 하고, 빌더 패턴? cascading을 이용해 쉽게 API 사용/확인이 가능하게 코드 작성
- 모델 수정
- CSRF 체감상 50번째 재학습
- CSRF는 확실히 Cookie의 Samesite와 관련이 많다고 느껴짐
241025(Fri)
- Celery 학습
241026(Sat)
241027(Sun)
Week 44(1028-1101)
241028(Mon)
- Workflow 개발을 위한 공부와 고민
- Airflow 살펴보기
- 사용하지 않더라도 DAG 구조는 응용해서 무한 반복 문제등을 방지할 수 있을 듯
- Celery 사용해보기
241029(Tue)
- 솔리드 커넥션 웹 개발
- 스피너 개발
- django-celery-results 사용
- Celery 결과 저장을 위해 Django 백엔드를 사용하게 도와주는 라이브러리
- django-celery-beat 사용
- 일정 주기 또는 cron으로 태스크를 실행해주는 것을 도와주는 라이브러리
- 재밌었던 건 일출 같은것도 조건으로 걸 수 있었다는 것.
- Django 로그 기록법 공부
- 일자별 로그 파일에 기록 방법
- AWS CloudWatch를 사용할 수도 있다는 것을 알다
- 비용적으로 보았을때 단기적으로 저장하고 alert등이 필요한 중요 로그는 CloudWatch를 사용해도, 오래 저장할 중요도 낮은 로그는 S3등에 보존하는 것이 괜찮을지도.
- Django 로그의 ERROR - WARNING - INFO 등급등을 활용하는 방식으로
- 다만 Celery는 별도 프로세스라 장고 logger를 이용해도 기록되지 않는 것을 확인. 별도의 로깅 설정이 필요할듯
- nested many 필드가 있을때 수정 API 엔드포인트 구현에 대한 고민
/groups/21/users/32
같은 느낌으로 세부 내역에 대한 수정/삭제를 해도 될듯- 삭제를 할때 번호가 줄어들어 이후 요청에 문제가 생길 수 있는 것을 주의 해야할 듯(API 사용측에서)
- 또한 순서 변경이라면 이 방식은 사용하기 어려움
- json patch라는 json 수정을 위한 표준을 알게됨.
- celery task 결과에 한글 유니코드 인코딩이 적용되지 않는 문제
- 오류라고 생각했는데, 잘 검토해보니 애초에 인코딩이 적용될 이유가 없었음.
- 왜냐하면 json형식의 결과라 일단 눈으로 읽을 수는 있는데, 이걸 잘 읽을 수 있게 보장할 필요는 사실 없음. 이건 알아서 인코딩해서 읽어야할 문제니깐.
- 즉 json 형식이 아닌 pickle 등의 형식으로 serialzie 하면 애초에 읽을 수도 없는데, json이라서 그나마 영어는 제대로 볼 수 있는 것에 감사해야한다는 느낌?
- 즉 읽어야 한다면 그때그때 json.load()로 처리해서 읽자.
241030(Wed)
- 파이썬 test coverage 라이브러리인 coverage를 알고 사용해봄
- 그닥 유용하지 않다 느껴져 도입은 안할 듯
- single table strategy에 대해 알아보고 적용할지 고민
241031(Thu)
- 스프링 빈 생명주기 학습
- InitializingBean, DisposableBean 인터페이스
afterPropertiesSet()
,destroy()
를 오버라이드 해서 사용- 스프링 전용 인터페이스에 의존, 코드를 변경할 수 없는 외부 라이브러리에 적용하기 힘듦
- 빈에 초기화, 소멸 메서드 지정
@Bean(initMethod = "init", destroyMethod = "close")
과 같은 방식- 메서드 이름 자유롭게 지정 가능, 스프링 코드에 의존하지 않음, 외부 라이브러리에도 적용 가능
- 또한
destroyMethod
에는 추론 기능이 있어 자동으로close()
나shutdown()
이라는 이름의 메서드를 자동으로 찾는다. 싫다면destoryMethod=""
로 지정 @PostConstruct, @PreDestroy
어노테이션 사용(권장)- 그냥 메서드 위에 붙여주면 되서 편리
- 스프링에 종속적이지 않은 자바 표준 기술임
javax.annotation.PostConstruct
- 외부 라이브러리에 적용하기는 힘듦
- 빈 스코프 학습
- ACC Inha 세션
- 캐시와 Redis
- Celery cron job(beat) 실험
- 동시에 많이 실행되더라도 task 실행에 0.12~0.2초밖에 걸리지 않음. 이것도 대부분 네트워크와 DB단의 병목일 것
- 문제가 될 수 있는 점은 외부 API서버에서 시간 간격당 API 요청횟수 제한을 걸어둔다면 문제가 될 수도. 이를 위해 오류 발생시에도 자동 복구를 할 수 있는 구조를 설계하는 것이 중요.
- 비밀번호 평문 저장에 대한 조사
- 모든 비밀번호를 환경변수에 저장할 수는 없으니, 디비에 저장한다면 양방향 암호화-복호화 가능한 키를 사용하고 해당 키만 환경변수에 저장하는 것이 좋을 듯