항해 3기 10주차 WIL 2021.11.15~2021.11.21

CH_Hwang·2021년 11월 21일
0

항해99

목록 보기
12/14

2021.11.15

오늘은 하루종일 타입스크립트를 공부했다.
일단 타입스크립트를 공부하면서 느낀건 굉장히 객체지향적인 언어라는 생각이 들었고 이걸 우리 express에다가 적용할때 과연 객체지향적으로 적용하는것이 맞을까라는 생각이 들었다. 그래서 일단 팀원들과 회의할 때 첫번째 목표는 타입정하는걸로 migration을 하고 그 후에 객체지향적으로 바꿔보자!라는 말을 했다.

팀 전체회의에서는 디자이너분들의 피드백과 팀 전체 기획방향을 정했다. 일단 백엔드는 타입스크립트로 migration하는것이 일단은 확정된 부분이고 프론트분들은 리팩토링, 테스트코드, 디자이너 피드백 수용이 최우선 방향인 것 같다.
추가기능에 대해서는 일단 확정된 것은 댓글과 게시물 리스트(검색, 프로필페이지에서 리스트로 나오는 것)의 페이지네이션이 확정되었고 그 외에 재미요소를 추가시켜줄 추가기능들은 시간적인 부분때문에 일단은 확정시키지 않았다.

그리고 이번 회의때 느낀바로는 내가 생각보다 욕심이 참 많은 사람이라는 걸 조금 깨달았다. 가족들과 있으면 나는 항상 조금 조용히 있고 (고집스러울땐 한없이 고집스럽긴 하지만;) 왠만하면 가족들의 의견에 따르는 편인데, 내가 하는 분야에서는 실력은 되지않고 욕심만 많은 사람이라는 걸 이번에 실전프로젝트를 하면서 조금 뼈저리게 느끼고 있다. 리액트는 하나도 할줄도 모르는 녀석이 백엔드 코드 이제와서 조금 칠 줄 안다고 이것저것 해야한다. 해주세요 요구하는게 그들에게는 반감으로 다가올 수 있겠다는 생각이 든다.

'내가 조금 더 잘했더라면'

이 문구가 항해를 진행하면서 내가 느낀 절망감중 가장 큰 절망을 안겨준 녀석이 아닌가 싶다. 잘하고 싶다.
정말 잘하고 싶고 더 많이 알고싶다. 시간이 해결해 줄 문제이기도 하지만 그 시간을 최대한 단축시키고 싶다.
욕심이라면 욕심이다. 그래도 최선을 다해서 잘해질 것이다.
나는 원래 백엔드 스페셜리스트가 되고 싶었다. 하지만 이번에 실전프로젝트를 하면서 깨달은 것은 풀스택 개발자가 되어야겠다고 생각이 들었다. 풀스택 개발자가 되서 내가 힘들어하는 사람이 누구든 도와줄 수 있는 사람이 되자고 마음을 먹었다. 나는 최선을 다할 것이다.

타입스크립트로 공부용프로젝트를 진행하고있다.
타입스크립트 공부 repo
공부하면서 느끼는건 아직도 내가 객체지향적인 언어에 굉장히 약하고 이해하지 못하는 부분이 많다고 느껴진다. 또한 ORM도 모르면서 내가 쓰고 있다는 생각이 든다. type ORM의 경우에는 join문을 쓰는게 어렵다는 이유로 현재는 sequelize(현재 실전프로젝트에서 쓰고있는 ORM)로 바꾸어서 하고 있는데, 생각대로 되지 않는것 같아 답답하다.

2021.11.16

오늘 타입스크립트로 서버를 구축하던 중 sequelize 관계설정에서 오류가 있어서 하루종일 씨름을 했던 것 같다.

현재 자바스크립트로 짠 코드에서는 관계설정 중 either가 user의 id를 user라는 foreignKey를 가지고 있는데, 타입스크립트로 관계를 짜다 보니

Error: Naming collision between attribute 'user' and association 'user' on model either. To remedy this, change either foreignKey or as in your association definition

이런 오류가 뜬다.
찾아보니 column name과 reference name이 같을 때 생기는 에러라서 foreignKey 이름을 바꾸거나 as를 사용하라는데 그렇게 되면 user라는 이름으로 db에는 column이 설정이 되지 않는 경우가 생겼다. 물론 이렇게 사용만 하면 되지만 그로인해 바꿀 코드들과 테스트코드들이 기다리고 있어서 이걸 꼭 해결해야겠다고 생각을 하고 하루종일 씨름을 했던 것 같다. 또한 오늘 저녁회의때는 꽤 긴 회의를 했다(약 3시간정도) 오늘 저녁때 제대로된 기능확정 및 앞으로의 방향성을 정하는 시간이었는데, 투표로 대부분을 정한 것 같다.

2021.11.17

foreignKey 네이밍 문제에 대해서는 일단 as로 회피하는 법을 사용하기로 했다. 이번 일을 계기로 ORM에 대해서 조금 더 공부해봐야겠다는 생각이 들어서 프로젝트가 끝나면 orm을 이용해서 한번 더 프로젝트를 따로 진행해봐야겠다는 생각이 들었다.

마이그레이션 작업을 진행했다. 일단은 팀원 한분이 시골에 내려가셔서 코딩을 하기 어려운 환경이라서 오늘은 그냥 공통적으로 쓸 app.ts, server.ts model설정 및 관계설정만 만들었다.

내일부터 아마 본격적으로 기능을 나누고 기능 나눈대로 migration을 하지 않을까 싶다.

2021.11.18

winston에서 logger.stream에서 문제를 발견했다.


이슈가 발생된 logger.ts

위와 같은 대량의 이슈가 발견됐는데, 이를 해결하기위해서 찾았을때 나와 같은 이슈를 가진 사람이 올린 글을 보게 되었고 stream을 바로 로거에 추가해라 라는 답변을 보았다.
https://github.com/winstonjs/winston/issues/1385


변경된 logger.ts

위와 같이 stream 자체를 export해서


app.ts에다

app.use(morgan('dev', {stream:logger.stream})

을 사용하는 것이 아닌 위와같은 사진으로 stream을 바로 넣어줬고 결과적으로 해결이 되었다.

중간에 계속 stream.write is not a function이라는 에러가 발생되긴 했지만 이부분은 내가 logger.ts에서 까먹고 맨 아래있던

module.exports = logger;

를 제거를 하지 않았기에 생긴 문제여서 삭제하고 난 후에 잘 되는 것을 확인했다.

타입스크립트로 migration을 완료했다.
일단은 기존 javascript에서 타입만 거의 지정해준 개념으로만 migration을 해줬지만 전체적으로 일단 ts파일로 바꾸긴 했다. 그리고 이후에 객체지향적으로 리팩토링을 하지 않을까 싶다. 타입스크립트로 migration을 하면서 생각보다 난항이 있었다. 예를들면 기본 함수에서 object의 value를 이용하는 함수의 경우 sequelize.query로 반환된 값이 object[]의 타입을 가지고 있어서 object안에 있는 key나 value를 읽어오지 못하는 경우가 있었다. 그래서 object[]로 되어져 있는 부분을 interface로 sequelize.query의 반환값을 지정해 주고 했더니 해결이 되었다.

2021.11.19

오늘은 객체지향에 대한 공부를 조금 하고 사용자 피드백을 받은 부분에서 쉬운 부분만 일단 즉각적으로 해결했다. 이를테면 벨리데이션이라던가 그런부분에 대해서는 바로바로 할 수 있기 때문에 바로바로 하는게 좋다고 판단하여 피드백을 수용하고 고쳤다.

로그인에서 오류가 생겼다. 아이폰 특정유저들의 브라우저(꽤 많이 발생하는것 같고 브라우저의 종류는 다양해서 특정지을수 없을 것 같다.) 에서 로그인이 되지 않는 이슈가 생겼는데, 이는 아이폰 보안정책때문에 쿠키가 넘어가지 않는 이슈인것 같다.(크롬 시크릿모드와 같은 현상인 것 같다) 이걸 해결하기위해 유저들의 보안정책을 바꾸라고 할 수 는 없기 때문에 기존에 서버에서 쿠키를 발급하던 방식 대신에 서버에서 프론트로 jwt를 넘겨주면 프론트에서 저장하는 방식을 택할 것 같다.

2021.11.20

nginx에서 동일 ip일때 api요청의 갯수를 제한했다. 악의적인 공격을 막기위해 초당 10개로 했고 옵션은 아래와 같다.

하나씩 살펴보자면,
limit_req_zone 이라는 것은 요청-request를 확인하고 이를 제한하기 위해서 특정한 영역(zone)을 선언한다는 의미이다.
$binary_remote_addr 은 nginx 에서 기본적으로 제공하는 내장 변수로, 클라이언트의 IP를 기준으로 제한을 하겠다는 의미이다.
zone=depend_dos 라는 것은 zone 의 이름을 설정하는 것으로, zone의 이름은 임의로 변경이 가능하다
30m 이라는 것은 zone에서 활용가능한 share memory size 로. 10M 정도면 충분하다.
rate 는 요청-request 의 비율로, 여기에서는 초당 10개 이상의 요청-request 이 유입되면 제한을 하겠다는 의미이다. (r/s, r/m 가능)

burst 를 적용한 것은 rate(여기서는 10r/s) 이상의 request-요청에 대해서 5개 까지는 queue에 보관하도록 하고, 그 이상은 에러를 반환하게 한다는 의미이다.

nginx에서 첫번째로 api요청 갯수를 제한했고 서버에서도 미들웨어를 사용하여 api요청 갯수를 제한했다.

express-rate-limit 모듈을 사용하여 구현한 api limit

1초에 최대 15번까지로 일단은 설정해 놓았는데 현재 그냥 예시로 설정을 해놓은 것이고 추후에 nginx와 통일을 할 계획이다.

또한 날짜를 프론트에서 만들어서 보내주고 있는 형식을 백엔드에서 만들어주는 형식으로 바꾸어주었다.
기존에 프론트에서 만들어주는 형식은 프론트와 서버의 통신사이에서 시간지연이 있을경우를 생각하고 프론트에서 시간을 만들어 주었는데, 너무 디테일한 부분까지 신경을 쓴 것 같고 날짜를 조작해서 보낼 수 있다는 조언을 들었다. 그래서 백엔드에서 validation이 필요할 것 같다고 하였고 내부에서 회의를 한 결과 신뢰성을 위해서 그냥 백엔드에서 날짜를 만들어주는 방법으로 바꾸었다.

DAU를 측정하는 방법을 생각해봤을때 현재까지 생각나는 방법은 MAC address로 하는 방법, ip주소로 하는 방법과 cookie에 uuid값을 넣어줘서 하는 방법이다.
현재 MAC address를 이용한 방법은 client의 mac address를 가져올 방법이 없어서 불가능하다.

  1. ip주소로 DAU를 측정하는 방법은 페이지에서 접속했을때 ip주소를 받아와서 저장공간에 날짜와 함께 넣어둔 후 날짜를 조건으로 카운트 하는 방법이다.

장점:

  • 구현이 쉽다.

단점:

  • wifi같은 사설ip에 대해서 분별이 불가능하다
  1. 쿠키에 uuid값을 넣어줘서 측정하는 방법은 페이지에서 접속했을때 쿠키에 uuid를 만들어서 넣어준 후 저장공간에 날짜와 함께 넣어둔 후 날짜를 조건으로 카운트 하는 방법이다.

장점:

  • wifi같은 사설ip에 대해서 분별이 가능하다.

단점:

  • 기기별 분별이 불가능하다.
  • 구현이 복잡하다(expired를 따로 해당날 자정으로 설정해줘야하고 uuid를 만들어줘야함.)

정리를 해봤을 경우 서로 어떤 특정조건에서는 분별이 불가능하기 때문에 ip를 이용한 DAU 측정방법을 할 것 같다.

2021.11.21

오늘은 알고리즘을 위주로 공부를 했다.
사실 요새 프로그래머스 1단계 위주로 알고리즘 스터디를 하고있었는데 다음주부터 프로그래머스 2단계로 한다고 해서 오늘까지 프로그래머스 1단계를 다 풀려고 했지만... 아직 조금 남아서 더 풀고자야겠다..
알고리즘은 현재 깃허브에 따로 정리중이다!
깃허브주소

0개의 댓글