본문 바로가기

회고/TIL

(20)
Database - 정규화 🔥 정규화는 왜 진행해야될까? 정규화를 통해 보다 일관성 있고 정확한 데이터들을 효율적으로 관리할 수 있게 된다. 아래 설명할 제 1, 2, 3 정규화를 통해, 혹은 역정규화를 통해 상황에 맞게끔 데이터들을 관리할 수 있게 된다. 제 1 정규화 아래와 같이 만들어진 Students 라는 테이블이 있다 가정을 해보자. ID 이름 과목명 1 김 철수 JavaScript, TypeScript 2 정 미남 Java, C++ 3 백 미녀 Python 어차피 이름이 같기때문에 그안에 속한 과목명끼리는 한꺼번에 묶어도 좋을것 같다. 그럼 과목명 이란 속성에 여러가지 데이터가 한꺼번에 들어가도 괜찮을까? 💩 No 제 1 정규화는 하나의 속성(Column)당 하나의 데이터만을 가지는 것을 의미한다. 그래서 아래와 같이..
홈서버 구축기 -1 시작하게 된 이유 부트캠프를 진행하면서 AWS를 사용할때 좋지도 않은 성능의 서버를 쓰면서 과금이 될까봐 조마조마 한것이 늘 불만중에 하나였다. 집에서 놀고있는 몇년 지난 노트북 조차도 프리티어로 제공되는 서버에 비하면 양반이었기 때문인데 그래서 더욱 도커를 활용한 나만의 서버를 구축하는것에 욕심이 생기게 되었다. 도커는 무엇일까? 내가 Mac OS를 쓰고있는 지금, 만약 window 운영체제를 사용하고 싶다면 가상환경을 설치해서 그 위에 돌리는 수밖에 없을것이다. 그러면 내 현재 기본 운영체제인 Mac 위에 window를 또 설치해서 불필요한 OS 가 탑재가 되고 그 위에서 window의 프로그램만 돌아가는 상황인데 여기서 중요한 점 내가 필요한건 프로그램이지 window가 아니다 윈도우는 필요 없고..
webRTC - socket io webRTC - Socket 현재 최종 프로젝트중에 webRTC를 활용한 서비스를 구현중에 있다. 예상치 못한 문제에 봉착해 꽤나 애 먹은 문제를 최종적으로 어떻게 해결을 했는지까지의 여정을 한번 적어보려 한다. 배포 전 & 후 배포하기 전, 로컬 상황에서는 총 3개의 서버를 구동시켜야 했다. ( 원래 총 4개인데 AI 관련 서버는 제외 ) 메인 서버, 채팅 서버, 프론트 서버 이렇게 3가지 였는데, 그 이유로는 채팅 서비스에 접근하기 위해서는 로그인된, 즉 검증된 유저만 접근이 가능하게끔 로직을 구현했고, 그래서 메인서버에서 토큰을 쿠키 값으로 받아온 이후에 접근을 해야만 했다. 프론트의 포트는 3200, 메인서버는 3000, 채팅서버는 8080이고 게이트웨이가 8000이었다. ( 일부러 구분점을 잡..
DAU & WAU & MAU 최종 프로젝트 ' Drink!t ' 을 진행중에 WebRTC 를 통한 화상채팅을 구현중에 튜터님이 던져주신 키워드였다. 나의 궁금증은 ' 하나의 Namespace 에서 얼마만큼의 채팅방을 활성화 시킬수있으며 ( 얼만큼의 트래픽을 감당할 수 있는지 ) 어느정도 선에서 Namespace를 분리해주는 기준으로 삼아야하는가 ' 였다. 그에 대한 답변으로는 ' 때에 따라 맞는 자료구조를 선택해 분리해주는건 당연하다. 중첩된 데이터를 사용할 경우 시간 복잡도가 증가하는건 자연스러운 것이니 그에 따른 채널 분리를 고려한 것은 잘 한 선택이다. 다만 현재 프로젝트에선 굳이? 라는 생각이다 ' 라고 받았다. 그러면서 얻은 키워드, ' DAU ' 에 대해 알아보려 한다. DAU ( Daily Active User ) & ..
Postgres - Datatype 프로젝트를 진행중인 같은 팀원분의 에레를 핸들링하다가 알게된 사실! MySQL에서 Postgresql 로 넘어오면서 당황한 것중 하나가 Datatype을 bigint 로 설정해주었을때 불러오는 값이 number 타입인지 string타입인지 에 대한것이었다. 상품 관리 엔티티에는 totalStock 이란 컬럼이 존재를 했고 타입을 bigint 로 준 상황. 상품의 정보를 find 메서드를 통해 가져와 보니 자꾸만 string 값을 반환을 해주어서 서비스 로직 처리했을때 원하는 결과값을 못얻어냈다. 유저가 물품 3개를 구매를 했다가 취소를 했다 가정을 했을때, 그럼 totalStock에는 + 3 이 되어져야 하는 로직이다. 근데 String 타입을 불러오는 바람에 현 재고가 30 개라 가정을 해보면 '33개..
Redis - cache Cache 구조 ✨ Keyword ✨ Web server Cache DB Look aside Cache 🔥 과정 1. Server API는 Caching 된 data가 있는지 먼저 메모리에서 확인 2. Cache에 data가 존재한다면 반환 3. DB에서 data 가져오기 4. Cache에 저장하면서 데이터 반환 ❗️ 일반적으로 많이 쓰이는 방법 Write Back 🔥 과정 1. Server API는 모든 요청에 관한 데이터들을 Cache에 저장 2. Cache Memory는 "특정시간" 동안 데이터를 축적 3. Cache에 있는 데이터를 DB에 저장 4. Cache Refresh ❗️ 체크사항 - 캐시 메모리는 재부팅 혹은 장애로 인한 데이터 손실에 대한 우려가 있다. - Look aside Cache..
Sequelize - Scope Scope 말 뜻 그대로 '범위' 에 대한 개념으로 보면 될 것 같다. 나는 typescript 관련 프로젝트를 하며 ORM으로 sequelize를 사용했는데, 사용을 하다보니 Repository Layer 에서 늘 include로 연계된 모델의 데이터들을 JOIN 해오는 것이 뭔가 지저분해 보였었다. 해서 관련된 내용이 있지 않을까 하고 공식문서를 찾아보던 중, Scope 라는 개념을 접하게 되었다. 먼저 아래 코드를 보자. @DefaultScope(()=>({ attributes: ['date','time'], })) @Scopes(()=>({ full : { attributes: ['date','time'], include : [ { model : Show, }, { model : Seat, as ..
Typescript - Generic Ts 를 공부하면서 느낀 점으로는 굉장히 '엄격'하다 였다. 그로인해 메서드를 만들어줄때도 타입을 일일히 지정을 해주고, 반환 값에 대한 타입도 명시해주는 일을 하다보니 무언가 비효율 적이란 생각도 들게 되었었다. 나는 특정 데이터를 받아 Null 값을 체크하는 메서드를 만들고 싶었다. 그럼 그 값이 string 일때, number 일때, boolean 일때 메서드를 일일히 다 만들어 줘야 하는걸까? 아니면 💩 과도 같은 any 타입을 지정해서 처리를 하면 될까? 이때 나온 해결책이 바로 Generic 이다. 타입 스크립트 특유의 엄격함을 유연하게 관리하게 해줄 녀석이다. function checkNullString( data : string ) : string { if ( data === undefin..