Skip to content

1주차 멘토링

Ji Yoon Choi edited this page Nov 16, 2022 · 8 revisions

질문

1. DB 에 들어가는 문자열 값들 중에서 고민이 되는 부분이 있습니다.

  1. NOT NULL 로 하고, 빈 문자열을 기본으로 넣어놓는다.
  2. NOT NULL 조건을 아예 넣지 않고, NULL 을 기본으로 넣어놓는다.

2. 필터링 관련 api 요청 방식

기술 스택 or 분야를 선택하는 드랍 박스에서 선택이 이루어질 때마다 데이터를 요청하는 것이 좋을 지,

-> 사용자들이 검색을 하는데 더 편하지만, api 요청이 더 많이 이루어진다.

아니면 드랍 박스 하단에 검색 버튼을 마련해놓고, 선택 완료 후 데이터를 한 번에 요청하는 것이 좋을 지

-> api 요청이 버튼이 클릭되는 순간에만 이루어지므로 서버의 부담이 적다.

이 두 가지를 고민 중인데, 추가적으로 고려할만한 사항이 있을까요?

3. 기획서(figma, erd 포함) 조금 더 고려하면 좋을 요소가 있을지?

image

4. env 파일은 어떻게 관리하는 것이 좋을지?

5. 기능과 관련하여 추가적으로 고려할만한 기술 스택이 있을지?

6. 나중에 채팅 기능을 추가하게 된다면, DB 구성을 어떻게 하는 것이 좋을지?

7. JWT 관련 질문사항

Access Token 과 Refresh Token 을 둘 다 사용할 때, refresh token 을 이용해서 acces token 을 재발급 받는 절차에 대해 궁금증이 있습니다.

  1. 평소에 access token 만을 보내다가, 만료됐을 때만 refresh token 가지고 다시 요청을 보낸다.

    1. client -> server : access_token 전송
    2. server -> client : access_token 만료됐으니 refresh token 이 필요하다.
    3. client -> server : refresh_token 전송
  2. 평소에 access token 과 refresh token 을 항상 같이 보낸다. -> 만료되면 바로 access token 을 재발급 해준다. access_token + refresh_token


멘토링 답변

회원가입을 따로 구현할 것인지?

  • 회원가입이라기보단 깃허브 / 구글 로그인을 받고, OAuth 인증 절차를 거친 후 추가적으로 필요한 정보만 받아올 예정
  • (탈퇴 페이지도 구현하실거죠?)

타겟이 PC 위주인지?

  • 현재는 PC 위주로만 생각하는 중 => 시간상 PC / 모바일 둘 중 하나만 고르는 것이 좋겠다

JWT 관련 질문 => 우리만의 토큰을 발급할 것 같다

  • 액세스 토큰의 해킹 위험성을 줄이기 위해 리프레쉬 토큰을 같이 사용하는데, 서버와 클라이언트가 주고받는 절차를 어떤 식으로 구성해야 보안상 / 리소스적 이점이 있을지

    • 리프레쉬 토큰이 탈취되면 서버에서 삭제 시도 등으로 보안을 막을 것
    • 이 방식이 좀 낯설다 => 토큰을 하나만 사용하는 회사도 있음
  • 토큰 하나만 사용하는 방법: 액세스 토큰의 만료 기간이 길고 (1~2주 정도), 매번 사용할 때마다 새로 발급을 해 준다

    • 리프레쉬 토큰을 사용함으로써 얻는 보안적인 이점은 조금 애매하다
    • 리프레쉬 토큰은 서버에만 저장하고, 액세스 토큰은 서버와 클라이언트에 동시 저장, Valid 여부 뿐만 아니라 DB 에 저장된 액세스 토큰 값과 똑같은지 체크한다
    • 탈취되었을 때 방어가 전혀 안된다... Valid 체크를 추가로 진행해야 함 => 서버에서 추가적인 절차를 진행해야 한다
  • 로그인을 2주동안 잡는 경우도 있고 어렵긴 하다

OAuth

  • 로그인 처리에 대한 부분을 사람마다 다르게 구현하더라... 방식을 하나로 통일하는 것이 시간이 걸릴 것

  • 구글 / 깃허브 토큰값은 유지 시간이 매우 짧다

    • 계속 Refresh를 하거나
    • 구글 / 깃허브 토큰을 이용하여 데이터만 받아오고, 우리가 자체적으로 토큰을 만들어서 지속시간을 조금 더 길게 잡거나

NOT NULL vs NULL

  • NULL 보다 NOT NULLNULL 체크를 할 필요가 없어 성능이 좋다?? NULL로 저장하기 vs '' (빈 문자열) 로 저장하기
    • 성능은 DB마다 차이가 있다
    • 성능 관점으로 보기보단, NULL 이 담고 있는 의미에 대해서 생각해보는 것이 좋을 것 같다
    • NULL은 값이 없음을 나타내는데, '' (빈 문자열) 은 '값이 없다' 라는 의미가 퇴색되는 감이 있다
    • 실질적으로 필요한 것만 NOT NULL로 두고, NULL도 적절히 사용하는 것이 좋다

검색 바 API 호출 위치

  • 필터링 옵션이 체크될 때마다 API 호출을 시킨다 vs '선택 완료' 등의 버튼을 클릭할 때만 한번에 API 호출을 시킨다
    • 전자: 사용자에게 조금 더 좋은 UX 경험을 줄 것 같다
    • 후자: 서버에 부담이 적다
    • 멘토님: UX 경험을 우선시해야 한다고 생각함, DB 때문이라기에는 이것을 해결할 방안이 프론트엔드 시점으로도 꽤 있다
    • 대표적인 것이 Throttle 기술: 체크박스를 1초에 10번 눌렀다고 10번 요청이 가지 않도록, 특정 기간동안 한 번의 이벤트만 발생할 수 있게 막아주기
  • 백엔드에서도 부하를 줄일 수 있는 방법이 많다 => Redis 와 같은 캐시를 붙이거나, 검색과 같은 경우엔 검색에 최적화된 기술들을 붙여 사용함
    • Elastic Search: 특정 체크박스를 선택했을 때 어떤 데이터가 나오는지 미리 인덱싱을 해두고, 부하가 많이 오더라도 인덱싱한 결과값에서 빠르게 데이터를 가져올 수 있다
    • 데이터가 많을 경우 DB에 부하가 생기기 마련임, JOIN QUERY 같은 걸 이용하기보단 (검색에 한해서) Elastic Search 를 붙여 별도의 인덱싱 과정을 덧붙이는 일이 많다
    • 프론트엔드 - 백엔드 둘다 고려해봄직한 사항인 것 같아요
    • 다만 저런 체크박스 형태의 검색창은 캐시 히트율 (Cache Hit Rate) 가 비교적 낮아보인다 (다른 사람들과 키가 겹칠 일이 드물어보임) => redis cache 의 활용이 그렇게 유의미할 것 같진 않다

기획서와 ERD 관련, 조금 더 덧붙이거나 고려해봄직한 요소가 있을지?

  • 이 프로젝트와 비슷한 프로젝트를 멘토링해 본 경험이 있다

  • 우선순위 Stacks => 여러 스택이 쌓일 텐데 어떻게 이용할 것인지?

    • 구분자를 이용해서 데이터를 연속해서 저장하고, 클라이언트 측에서 split 을 하려고 했다
    • 클라이언트 쪽에서 스택 종류를 따로 가지고 있어야 할 듯하다
    • 멘토님: 프로필을 생성할 때, Stacks에 이미 값을 넣었다는 사실에 관한 validation이 필요할 듯한데
    • 프론트엔드의 정보는 신뢰할 수 없다는 것 (해커가 보냈는지, 우리가 보냈는지) 을 염두에 두어야 한다
      • => 우리가 정해놓은 스택에서만 고를 수 있도록 설정하려 했다 (백엔드에서도 같이 사용하는 공용 상수를 가지고 검증 절차를 거칠 예정)
    • 백엔드에서 Validation 관련해서 고민할 거리가 굉장히 많을 것 같다
      • 프론트엔드 - 백엔드간 공통의 validation check 로직을 가진다면 이중 방어가 되므로 좋다
  • ERD 상에서 말씀드릴 만한 부분은 많지 않을 듯싶어요

env 파일은 어떻게 관리하는 것이 좋을까

  • cross-env

    • 환경을 여러 개 구성을 해놓는다 (로컬용 - local, 개발용 - dev, 배포 직전 작동 체크용 - stg, 배포용 - real 등)
    • local, dev와 stg, real은 아예 별개의 DB를 바라봐야 한다
    • 또한 환경별로 서로 다른 env 를 주입하여 사용해야 한다
      • 보통 Host 주소와 같은 값이 들어갈 듯 싶다
    • 여러 환경변수를 코드 내에서 조건문으로 분기하여 가져와 사용할 수 있다
  • env 파일은 .gitignore 을 이용하여 깃허브상에 올리지 않는데,

    • 올리긴 합니다
    • 시크릿 키들은 어떻게 하는지? => env 에 넣지 않는다
    • 다른 방법으로 injection을 고려한다
    • 보통 서버를 배포하는 스크립트에서, 별개의 파일에 들어있는 환경변수들 (또는 Github-secret 과 같은 변수) 을 가져와서 배포 과정에서 따로 주입한다
  • 시크릿 키를 실수로 push를 하는 순간 이 키는 무조건 공개되었다고 생각하면 된다 (커밋을 제거하더라도 git으로 복구할 수 있다)

    • 만약 실수로 Push하면, 그 키는 아예 삭제하고 새로운 키를 발급받아야만 한다

배포 방식

  • Github Actions
    • workflow 안에서 Github Secrets 안에 들은 변수들을 주입시켜줄 수 있으므로, 비밀 키들은 이렇게 관리하자

고려할만한 기술 스택

  • 어느 정도의 동시 접속자 수까지 대응할 것인지? 가 조금 중요
    • 동시 접속자 수에 따른 기술 스택이 전부 다르다
    • 사실 지금은 대규모 접속이 예상되지 않기 때문에, 지금만으로도 충분할 것 같다
    • 오히려 대규모 접속을 고려한 기술을 사용하게 되면, 공부할 내용이 너무 많아지며 리스크가 커질 수 있다 (기술 부채)
  • 기술 스택이 옛날 것 / 너무 과한 기술 스택 => 기술 부채로 이어짐
    • 더 많은 스택을 고려해보는 것도 좋겠지만, 한정된 시간에 빠르게 완성도 높은 프로젝트를 구현하는 것이 더 좋아 보인다

채팅 기능을 추가한다면 DB에 저장을 어떻게 할까요?

  • 채팅 데이터는 NoSQL에 저장하는 것이 효율적이다?
    • 정답이 없는 문제긴 하다
    • RDBMS - NoSQL 차이: 정합성이 중요한가? 약간 뒤틀려도 상관없나?
    • 채팅은 정합성이 중요한 것은 아니다 (회원, 좋아요 등은 정합성이 중요함)
    • 유저 DB도 NoSQL을 사용하는 것이 성능은 훨씬 좋다
  • 관계형 DB의 이점: 관계형 DB를 JOIN해서 API로 한번에 데이터를 내려줄 때 이점을 가짐
    • 요즘은 각각의 데이터가 별개의 API를 따르기 때문에, 사실상 관계성이 그렇게 중요하지 않아 보임
    • NoSQL DB는 비정규화된 데이터 => 채팅 한줄 한줄을 별개의 키로 잡아 각각의 Document로 받아오는 것은 부담이 될 수 있다
      • NoSQL은 하나의 도큐먼트로 구성이 된다 => 얼마나 잘 비정규화했는지가 NoSQL의 핵심
      • 20개씩 잘라서 하나의 도큐먼트에 담고 페이징하는 등의 방법
      • 카카오톡도 스크롤해서 위로 올릴 때 여러 개의 대화 내역이 불러와진다 => 페이지네이션 되어 있다는 증거
  • 이 프로젝트에서는 NoSQL이 조금 더 적합해보이긴 한다
    • 지금 바로 NoSQL을 도입해도 상관없어 보임
    • 유저 데이터를 비정규화된 하나의 테이블로 잡는 것이 적절하지 않을까?
  • 관계형 DB는 컬럼이 너무 많아도 좋지 않다 => NoSQL은 상관없는지?
    • NoSQL은 관계형 DB에 비해 엄~~~청나게 빠르다 (bson => binary json 으로 저장되므로 도큐먼트 하나의 크기가 매우 작다)
  • NoSQL 도입 시
    • 좋아요 데이터만 별도의 테이블로 나누고 (무한히 커질 가능성이 있음), 나머지는 무한히 증식할 만한 필드가 없어보여 하나의 테이블로 뭉쳐도 상관없어 보인다

Github Action으로 물리서버에 자동배포하기

멘토님 블로그

오버페칭 - 언더페칭, GraphQL

GraphQL과 Restful API

  • 대형 서비스에서는 큰 페이지를 그리기 위해서 API 호출 20~30개 정도를 한다
    • 쓸데없는 필드를 받는 경우가 생김, 클라이언트상의 부하가 발생하기도 함
    • GraphQL: 이 두 문제를 전부 해결해주는 기술
    • 백엔드와 프론트엔드 사이에 여러 개의 요청을 하나의 응답으로 반환해주는 미들웨어 서버를 두는 것
    • 만약 API 호출이 30개라면, 이 응답을 전부 하나로 합친 뒤, 중복된 필드나 쓸모없는 필드를 제거하여 정제된 단 하나의 응답으로 전송하는 것
    • 요즘 트렌드로 많이 사용되는 기술
  • Restful도 옛날부터 써와서 그렇지, 요즘은 슬슬 끝이 오고 있는 느낌
  • 백엔드에서 어떠한 필드에 준 데이터에 오류가 있는 경우 (타입이 부정확하거나, 제대로 된 데이터가 아닐 경우 등)
    • 중간 서버에서 타입을 체크해서 백엔드에서 보낸 데이터가 타입이 이상할 경우, 로깅을 해서 개발자에게 알려주기도 함
    • 프론트엔드에서 갖는 이점이 꽤 많을 것이다
    • 토이프로젝트로 한번 작성해보는 것도 추천
    • Apollo 라는 라이브러리를 많이 사용한다 (GraphQL 스펙을 구현한 라이브러리) => 한번 고려해봄직 합니다 (요즘의 대세)

얼리버드

프로젝트

개발일지

스프린트 계획

멘토링

데일리 스크럼

데일리 개인 회고

위클리 그룹 회고

스터디

Clone this wiki locally