# 발표 스크립트
## P1 - 표지
안녕하세요, / 온라인 공동구매 플랫폼 / ^'사자같이'를 개발한 / 팀 신안우이입니다.
'사자같이'는 / 어떻게 하면 사용자에게 더 ^좋은 경험을 제공할 수 있는지 고민했던 흔적이 많이 녹아있습니다. / 지금부터 그 고민과 해결 과정들을 / 공유해보겠습니다.
## P2 - 사자같이 소개
사자같이는 / 혼자 사기에 버거운 대용량 상품들이나 / 일정 금액이상 주문을 해야 배달이 되는 경우로 인해 /
개인으로 상품을 구매하는데 어려움을 겪고 있는 소비자들에게 / 가까운 동네 이웃들과 함께 공동 구매를 할 수 있도록 서비스를 제공해주는 플랫폼입니다.
~~이페이지에서 서비스에 대한 소개를 한번 더 언급해야할지 고민~~
## P3 - 소개 영상
서비스에 대한 간단한 소개 영상을 보여드리겠습니다.
## P4 - 개발 목표
저희 팀은 / 프로젝트를 기획할 때 / 토이 프로젝트의 느낌을 벗어나 / 실제 서비스하는 것처럼 프로젝트를 개발해보고 싶었습니다. ^내가 쓰고싶게 만들면 / 실제 서비스하는 프로젝트처럼 / 개발할 수 있다고 생각했습니다. 그러기 위해서는 / 좋은 사용자 경험을 최우선적으로 / 개발해야 한다고 생각하였습니다.
## P5 - 최고의 UX는 빠른 로딩
성격급한 한국인에겐 / ^빠른 로딩이 / 최고의 UX라고 생각하기 때문에 / 많은 데이터가 있더라도 / 유저에게 빠른 서비스를 제공하고 싶었습니다.
## P6 - 쿼리최적화
그래서, / ^100만개의 게시글이 있어도 / 빠르게 유저에게 서비스를 제공할 수 있는지 / 직접 테스트해보기로 했습니다. 결과는 심각했고, / 게시글들을 불러오는 속도가 너무 느려서 / 서비스를 제대로 사용할 수 없었습니다. / 저희는 이 문제를 해결하기 위해 / 먼저 원인을 분석하였습니다.
## P7 - 쿼리최적화(기존 방식의 문제)
기존 방식은 두 지점 간의 최단 거리를 구할 수 있는 / 하버사인 공식을 이용해서 근처 게시글을 가져오는 것이었습니다. / 처음에 구현된 방법에서는 / ^두가지 문제가 있었습니다.
첫번째로 / 일단 인덱스를 생성하지 않아 / ^풀스캔이 발생합니다.
두번째로 / ^계산된 컬럼에 대해 조건을 검사하기에 / 인덱스를 생성해도 타지 않았습니다.
## P8 - 쿼리최적화(해결방법)
먼저 / 인덱스를 적용할 수 있도록 / 근처의 게시글을 구해오는 방식을 변경하였습니다. / 계산없이 대소비교만 하여 / 인덱스의 ^범위 검색을 이용할 수 있도록 / 사각형 범위내의 게시글만 가져오도록 변경하였습니다.
## P9 - 쿼리 최적화 (해결방법)
다음으로는 / 적용할 ^인덱스를 만들려고 하였습니다.
팀원 모두 인덱스에 대해서 개념만 알고 있었고 / 직접 적용해본 경험은 없었습니다. / 알고었던 내용을 바탕으로 / ^위도와 경도에 의해 걸러지는 데이터가 매우 많았기 때문에 / 위도와 경도로 인덱스를 생성하는 것이 / 성능이 잘 나올 것으로 예상했습니다. / 예상한 바가 맞는지 확인하기 위해 / 직접 측정해보기로 하였습니다.
다음 스프레드시트는 / ^검색 조건과 적용할 ^인덱스의 경우의 수를 나누고, / 각각의 ^실행 시간을 측정해 기록한 것입니다. / 예상대로 / ^위도와 경도 컬럼에 대한 인덱스를 적용했을 때 / 가장 성능이 좋았습니다. / 기존 쿼리의 속도는 / ^3.4초로 측정되었었는데 / 개선하고나서 쿼리 속도는 / ^0.02초로 / 매우 큰 차이가 있었습니다.
## P10 - 쿼리최적화(개선된 방법)
앞서 두가지 방법으로 개선된 쿼리입니다. / explain으로 확인해보니 / 저희가 만든 인덱스를 잘 타고 있는 것을 확인하였습니다.
## P11 - 쿼리 최적화 (개선된 결과)
왼쪽의 이미지는 / 처음 방법을 적용했을 때의 메인 페이지 로딩 속도이고 / 오른쪽은 개선한 쿼리문을 적용했을 때의 로딩 속도입니다. / 측정 결과 / 약 ^4초에서 ^1.3초로 눈에 띄게 빨라진 것을 / 볼 수 있습니다.
- ppt에 로딩 속도 숫자 자체도 써주면 좋을 것 같다. gif 파일 시작하는 타이밍이랑 끝나는 타이밍이 달라서 첫번째에 보지 않으면 속도가 얼마나 빠른지 보기 어려움 (18페이지 처럼 하면 좋을듯)
## P12 - 쿼리 최적화 (1000만개 쿼리 최적화)
저희는 이에 만족하지 않고 / 데이터를 ^1000만개까지 늘려서 테스트를 해보았습니다. / 그 결과 / 개선된 쿼리로도 약 ^4초라는 / 긴 시간이 걸려서 데이터가 로딩 되었고 / 또다시 개선할 필요를 느꼈습니다.
## P13 - 쿼리 최적화
적용중인 쿼리에서 / 개선할 수 있는 부분들을 분석해보았습니다.
등호조건 여러개를 ^OR로 묶어서 하는 부분, / 너무 ^많은 행에서 조인 연산이 발생하는 부분, / 매번 행해지는 order by ^정렬 부분에서 / 개선할 수 있을 것 같았습니다.
## P14 - 쿼리 최적화 (OR vs IN)
기존 쿼리에서는 / 여러 개의 카테고리를 선택해 검색하는 경우 / ^OR을 사용해 조건을 작성하였습니다.
조사 결과 / ^IN을 사용하는 경우 조건을 찾을 때 / ^이분탐색을 활용해 오더 ^로그 엔 으로 찾고, / OR를 사용할 경우 오더 ^N으로 찾기 때문에 / MySQL에서는 IN을 사용해 이를 대체하는 것이 / 더 빠르게 동작한다는 것을 알 수 있었습니다.
## P15 - 쿼리 최적화 (너무 많은 행의 조인 연산)
기존 쿼리문은 post 테이블과 category 테이블을 ^조인하는데, / post 테이블에 1000만건의 데이터가 있어 / 1000만번의 join이 실행됩니다. / 비용이 많이 드는 작업인 join의 수를 줄일 필요가 있었습니다.
## P16 - 쿼리 최적화 (ORDER BY 정렬 비용)
그동안 게시글을 최근 순으로 보여주기 위해 / 직접 내림차순 정렬을 해주었는데, / ORDER BY에 따른 정렬 비용도 클 것으로 보았습니다. / 미리 정렬해 놓은 데이터가 있다면 / 게시글을 가져올 때마다 매번 정렬을 할 필요가 없어지지 않을까 / 생각했습니다.
## P17 - 쿼리 최적화 (바뀐 쿼리문)
해결 방법입니다.
ORDER BY로 데이터를 정렬시키는 대신, / id, / 위도, / 경도 순서의 결합 인덱스를 만들고 / id를 ^내림차순 인덱스로 설정하여 최신순으로 정렬된 데이터를 얻을 수 있도록 하였습니다.
그리고 조인 연산의 비용이 큰 문제를 해결하기 위해, / FROM 절의 서브쿼리에서 / post 테이블을 먼저 ^위도와 경도로 걸러내도록 하였습니다. / 이후 조인 연산은 / 경량화된 테이블에서 수행되므로 / 처음보다 연산 비용을 많이 절감할 수 있었습니다.
## P18 - 쿼리 최적화
왼쪽은 개선하기 전, / 오른쪽은 개선 후의 화면입니다. / 각각 로딩 시간은 ^4.2초와 ^1.2초로, / ^250%의 성능 향상을 이끌어냈습니다.
## P19 - 클라이언트와 서버간의 데이터 정합성(문제점)
다음고민은 / 클라이언트와 서버간의 / ^데이터 정합성이였습니다.
맨 처음 메인 페이지를 로드할 때 게시글을 가장 최신순으로 요청하여 가지고 오지만 / 로드 ^후에 작성된 게시글을 볼 수 없다는 문제, / 가져온 게시글들이 즉각적으로 최신화가 되지 않는 문제가 있었습니다. /
저희는 게시글 기반으로 서비스가 이루어지는 사자같이 프로젝트가 / 서버와 클라이언트의 게시글 상태가 다르면 / 사용자에게 불편함을 끼칠꺼라고 생각 하였습니다.
## P20 - 클라이언트와 서버간의 데이터 정합성(해결)
우리는 단순히 데이터의 ^정합성을 해결하고자 했기 때문에 / 비슷한 기능들을 제공해주는 다른 모듈보다 bundle 사이즈가 작고 / 공식 문서화가 잘 정리되어 있는 / ^SWR을 선택하였습니다.
SWR을 적용함으로써 / 앞선 ^2가지의 문제점 해결과 동시에 /
SWR의 특성인 ^캐싱을 통해 / 캐시가 있으면 캐시 데이터를 먼저 렌더링한 후 새로 요청한 데이터를 업데이트 해주어, / 부드러운 UX를 사용자에게 제공할 수 있었습니다.
## P21 - 클라이언트와 서버간의 데이터 정합성(결과)
다음 이미지는 / SWR이 적용된 화면입니다.
이미지의 오른쪽 화면에서 새로운 게시글이 작성된 후 / 왼쪽 화면이 다시 포커스 되었을 때 / 새로운 게시글이 반영된 걸 볼 수 있습니다.
다음페이지부터는 / ux 향상을 위해 노력한 사항들을 / 간단하게 소개하겠습니다.
## P22 - 무한스크롤
사자같이는 / 모바일 사용자를 타깃으로 개발되었고, / 모바일 사용자가 편리하게 사용할 수 있도록 / ^무한 스크롤 기능을 제공하여 / 사용자가 화면을 터치하는 수와 / 번거로움을 줄였습니다.
## P22 - 스켈레톤 UI
저희가 구현한 ^링크프리뷰같은 경우 / 오른쪽 이미지를 보시면 아시겠지만 / 로딩하는 속도가 다른 컴포넌트에 비해 많이 느립니다. / 그렇기 때문에 / 스켈레톤 UI를 통해 / 사용자의 체감 로딩시간을 / ^짧게 느끼도록 하였습니다.
## P23 - 로딩 UI
위치를 받아오는 상황처럼 / 유저가 기다리는 시간이 많을 경우 / ^로딩 페이지를 넣어 / 유저의 ^지루함을 줄였습니다.
## P24 - 화면 전환
^화면전환시 / ^애니매이션 효과를 주어 / 사용자의 행동에 반응하면서 ^자연스러운 느낌을 연출할 수 있도록 하였습니다.
## P27 - 채팅 이미지 확대
채팅방에 전송된 이미지를 클릭하면 / ^확대해서 볼 수 있도록 구현하였습니다.
## P28 - 검색 결과를 URL로 공유
^URL을 통해 / 다른 사용자와 검색 결과를 ^공유할 수 있도록 / 검색 조건들을 / 모두 URL에 포함하였습니다.
## P29
저희 팀의 발표내용은 여기까지이고 / 이제 QnA 시간을 / 갖도록 하겠습니다. 혹시 질문 있으신분은 / 말씀해주시면 감사하겠습니다.
## P30
지금까지 저희 사자같이 팀이 고려하였던 유저 경험을 위한 저희들의 노력에 관한 발표는 여기서 마치도록 하겠습니다.
# 예상질문
## SWR 관련
- SWR은 어떤 방식으로 동작하나요 ->npm 모듈을 직접 봐야하나?
- useSWR 동작 방식
- **캐싱된 데이터가 있으면 먼저 가져오며, 서버 데이터 가져온 후 마지막으로 최신의 데이터를 업데이트한다.**
key, fn, option을 인자로 받으면 key를 기반으로
저장소에 fn을 통해 서버로 부터가져온 promise객체와 현재 시간을 저장한다.
인자로 받은 option을 바탕으로 주기적으로 필요한 옵션은 특이하게 setInterval로 설정하는게 아닌 setTimeout으로 매번 실행시키며, focus 같은 이 벤트는 구독을 통해 해당 이벤트가 발생하면 revalidate시켜주는 형식으로 동작한다. 새로 가져온 데이터가 기존에 저장된 캐시와 다를 경우 업데이트 한 다.
- SWR은 어떻게 캐싱하지?
- JavaScript의 WeakMap 사용하여 pageKey(요청할 url)를 key로하고 요청한 url의 응답 데이터인 pageData를 value로 저장한다.
- 내부적으로 originalData와 캐시에 저장된 데이터를 stableHash hash후 비교하여(== Equal Operator) 다르면
- 해당 key(url)을 다시 요청하여 캐시와 originalData를 맞춘다.
- 참고 ===는 Strict Equal Operator, ===는 변수 유형을 고려하는 반면, ==는 변수 값을 기반
- swr에서 stableHash 동작 방식은?
- hash table도 JavaScript의 WeakMap으로 구성,
- hash의 결과는 string
- hash할 자료형이 Array이면 for문으로 돌면서 배열의 각 요소들을 다시 stableHash를 실행시켜 동작한다.
```
// github
result = '@'
for (index = 0; index < arg.length; index++) {
result += stableHash(arg[index]) + ','
}
```
- 자료형이 객체이면 해당객체의 키들을 정렬한 후 정렬한 키 순서대로 다시 stableHash를 실행시켜 동작한다.
```
// github
result = '#'
const keys = OBJECT.keys(arg).sort()
while (!isUndefined((index = keys.pop() as string))) {
if (!isUndefined(arg[index])) {
result += index + ':' + stableHash(arg[index]) + ','
}
}
```
- 둘다 아닐 경우에는
```
result = isDate
? arg.toJSON()
: type == 'symbol'
? arg.toString()
: type == 'string'
? JSON.stringify(arg)
: '' + arg
```
- SWR 사용하신 이유나 장점?
- 공식문서가 한글화가 잘 되어있다는 점
- 다른 비슷한 기능을 하는 react-query나 Apollo Client에 비해서 bundle 사이즈가 3.9KB로 가장 작아서 사용하였습니다.
- 캐시에 들이는 시간을 줄일 수 있어서 (개발비용 감소)
- react-query: 12.8KB, Apollo Client: 39.0KB
- SWR 단점?
- 옵션 설정에 제한적이다?
- 옵션 중에 revalidateAll 이라는 옵션이 있는데, true로 하면 모든 key에 대해서 다시
- 요청을 한다. 모든 key즉 url에 대해서 다시 요청을 하여 revalidate 시켜주기 때문에 클라이언트와 서버에 드는 cost가 상당한데 이 옵션을 상황에 따라 사용할 수 있게 하거나 사용하지 않게 하거나 상황에 따라 부분적으로 설정하지 못하는 점이 아쉽다.
- 정합성 유지때문에 렌더링하는데 시간이 오래 걸리는 것 같다
- 저희도 알고 있는 부분이고 추후 유지보수 단계에서 가상 스크롤을 도입해 해결할 계획입니다.
- 가상스크롤이 뭔가요?
- 돔에 모든 엘리먼트들을 띄우지 않고 현재 보고있는 스크롤(화면)에 해당하는 엘리먼트들만 돔에 렌더링하여 돔트리의 사이즈를 줄일 수 있고 불필요한 렌더링을 막을 수 있습니다.
## 쿼리 최적화 관련
- 사용하신 쿼리가 최적이라고 생각하시는 이유는 무엇인가요?
- 다양한 쿼리와 인덱스를 시도해보았고, 측정한 실행 시간 데이터에 근거해 가장 빠른 쿼리를 선택했기 때문입니다.
- 어떻게 측정하셨나요?
- mysql workbench에서 쿼리를 실행하고 결과로 나오는 시간을 기준으로 측정했습니다.
- 다만 같은 위치 조건으로 쿼리를 계속 실행하면 첫번째 이후의 결과는 캐싱이 되어서 더 빠르게 측정이 되었습니다. 이는 mysql 쿼리 캐시를 꺼도 마찬가지였습니다. mysql의 쿼리 캐시를 끄더라도 자체에 있는 innoDB buffer 그리고 이미 디스크에서 메모리로 올라온 많은 데이터들이 있기때문이라는 것을 알게되었습니다. 이후 쿼리 측정 관련하여 저희가 찾아보았고, innnoDB_buffer_pool의 사이즈를 최소화하면, 완전하진 않더라도 어느정도 비슷하게 측정 할 수 있다는 것을 알게 되었습니다.
- 쿼리캐시 : SELECT 쿼리문을 이용해서 조회한 값을 저장하고 있다가 같은 쿼리문을 요청하면 캐싱된 값을 응답해 주는 것
- [쿼리캐시](https://dev.mysql.com/doc/refman/5.7/en/query-cache.html)
- [innodb 버퍼 사이즈 변경](https://gre-eny.tistory.com/4)
- InnoDB가 뭔가요?
- mysql의 스토리지 엔진으로 자체적으로 메인 메모리 안에 데이터 캐싱과 인덱싱을 위한 버퍼풀을 관리해서 대용량 사용자나 데이터를 처리할 때 효율적인 작업이 가능해짐?!
- innoDB는 MySQL에서 쓰이는 스토리지 엔진으로 다수의 사용자가 동시접속 퍼포먼스가 증가하여 대용량 데이터를 처리할 때 최대의 퍼포먼스를 내도록 설게되었습니다. 자체적으로 메인 메모리 안에 데이터 캐싱과 인덱싱을 위한 버퍼풀을 관리합니다. [innoDB](http://www.rcy.co.kr/xeb/study/2538)
- Innodb_buffer_pool 란 무엇인가요?
- 버퍼풀은 innoDB가 엑세스할 때 테이블 및 인덱스 데이터를 캐시하는 메인 메모리 영역입니다. 버퍼풀은 자주 사용하는 데이터를 메모리에서 직접 처리할 수 있게하여 처리속도를 높이는 기능을 합니다. 당연하게도 버퍼 풀의 크기가 클수록 쿼리의 성능이 좋습니다. [innodb_buffer_pool](https://owlyr.tistory.com/23)
- InnoDB의 테이블 스페이스
- 왜 위도와 경도에 복합인덱스를 적용하셨나요?
- 저희는 검색할 때 현재 자기 위치를 기준으로 1km거리 내의 있는 게시글들을 필터링하고 싶었습니다. 이때 현재 본인의 위치를 기반으로 필터링 해야하므로 위도와 경도는 검색조건으로 꼭 들어갑니다. 또한 다른 컬럼들에 비해 위치 정보의 cardinality가 크기 때문에 더 빠른 효율을 위해서 위도와 경도에 복합인덱스를 사용하였습니다.
- cardinality는 뭔가요?
- 중복의 정도를 나타내는 수치입니다. 카디널리티가 높다는 건 중복도가 낮다는 의미이며, 그만큼 값이 겹치지 않고 다양하게 분포되어 있음을 뜻합니다.
- cardinality가 큰 컬럼에 인덱스를 사용하는 이유는 뭔가요?
- cardinality는 선택도와 비례합니다. 선택도란 해당 테이블의 레코드 수에 대한 카디널리티인데, 이 선택도가 클수록 데이터 집합에서 특정 값을 잘 골라낼 수 있다는 의미가 됩니다. 즉, 인덱스 적용시 카디널리티가 높을 수록 특정 레코드를 잘 골라낼 수 있어 효율이 좋습니다.
- 인덱스 사용시 단점도 알고 계신가요?
- 인덱스를 사용하면 기존의 테이블 뿐만아니라 비플러스 트리 구조도 있기 때문에 데이터의 값이 바뀔 때 비플러스 트리도 값이 바뀌어야 하므로 작업량이 늘어납니다. 따라서 인덱스는 데이터의 변화가 많은 테이블에서 사용하기엔 비효율적입니다, 인덱스 자체도 데이터이기 때문에 인덱스가 많아지면 중복된 데이터가 늘어나게 되어 적절한 생성이 필요합니다.
- 비플러스 트리가 뭔가요?
- 데이터베이스에서 빠른 탐색을 위해 비플러스 트리의 인덱스를 만들어 사용하며, Balancing Tree의 일종이므로 탐색에 O(log N) 시간을 소요합니다.
- 비트리와의 차이가 뭔가요
- 비트리를 확장한 것이 비플러스 트리입니다. 비트리가 모든 노드에 key와 value를 같이 갖고 있는 것에 반해, 비플러스 트리는 리프 노드에만 value가 저장되어 있습니다. 비플러스 트리의 리프 노드에는 트리에 저장된 모든 데이터가 링크드 리스트로 연결되어 있기 때문에, 비트리보다 순회 작업에 유리합니다.
- https://ssup2.github.io/theory_analysis/B_Tree_B+_Tree/
- https://wangin9.tistory.com/entry/B-tree-B-tree
- 검색어 검색은 어떻게 구현되어 있나요?
- WHERE LIKE로 정규표현식을 사용해 검색합니다.
- 정규식으로 검색하는 경우에 성능 저하는?
- 정규표현식이 풀스캔을 유발하긴 하지만, 검색어 풀스캔 이전에 위치와 같은 다른 조건에 의해 필터링되기 때문에 그나마 영향이 적을 것으로 판단하고 적용하였습니다. 또한 조건에 해당하는 모든 데이터가 아닌 LIMIT으로 가져오는 부분도 고려했습니다.
- TypeORM을 사용하신 이유?
- 객체지향적인 방법으로 데이터베이스에 접근할 수 있어 코드의 재사용성을 높일 수 있다고 판단했습니다.
- mysql 쿼리가 돌때 index 선택 기준을 아시나요?
- http://iloveulhj.github.io/posts/sql/sql-optimizer-principle.html
- https://juntcom.tistory.com/15
- 쿼리 옵티마이저가 여러 실행 계획을 만들고 그 중에 가장 비용이 적은 계획을 선택하게 되며, 이 계획에는 인덱스도 포함됩니다. 쿼리문에서 사용된 조건과 인덱스 통계 정보를 활용해 인덱스를 선택하게 됩니다.
## 기타 질문
- IntersectionObserver 동작 원리를 아시나요?
- 정확하지는 않지만 w3c(더블유쓰리씨) 깃허브 소스를 보니 스로틀을 이용해서 약 100ms 마다 viewport에 타깃이 교차하는지를 판단하는 식으로 동작하는 것으로 확인하였습니다.
- 스로틀이 뭔가요?
- 돔 이벤트를 기반으로 동작하는 자바스크립트 이벤트를 제어하는 방법으로 이벤트를 일정한 주기마다 발생하도록 하는 기술입니다.
- 참고 디바운스: 여러번 발생하는 이벤트에서, 가장 마지막 이벤트 만을 실행 되도록 만드는 개념이다. (이벤트의 그룹화)
- IntersectionObserver 사용하신 이유?
- 스크롤 이벤트를 이용해서 하려면 이벤트가 너무 자주 발생하여 스로틀이나 디바운스와 같은 방법으로 이벤트 발생 횟수를 조절해야 하지만 intersectionOberver를 구현하면 저희가 특별히 처리를 해주지 않아도 구현할 수 있어서 사용하였습니다.
- 좋은 UX라고 하면 어떤게 있을까요?
- 사용자의 동작을 최대한 적게 할수 있게 하는것
- 사용자의 동작에 바로 반응하도록 하는 것 (로딩이 되더라도 로딩이 된다는 걸 바로 표시)
- 사용자가 기대한 동작이랑 실제로 일어난 동작이랑 일치하는 것
- 디자인에 일관성이 있어야함
- 빠른로딩
- 무중단 배포는 할생각 안하셨나요?
- 구현할 내용과 학습한 내용이 많은 것 같아서 도커까지 사용하여 무중단 배포를 시도했을때 수박 겉핥기 식으로 될 것 같아 네트워킹 데이 이후에 하려고 생각했었습니다.
- nginx의 리버스 프록시
- nginx는 클라이언트의 요청이 들어오면 지정된 프록시 서버로 보내고 응답을 가져온 다음 클라이언트로 다시 전송합니다.
- 일반적인 프록시(forward proxy)
- 클라이언트에서 요청 시 Proxy를 통해 목적지에 요청하고 응답 받는 것을 말합니다.Proxy가 요청자를 대신해서 웹 사이트를 검색하거나 컨텐츠를 받아서 전달해주는 중계자 역할을 합니다.
- 리버스 프록시(reverse proxy)
- Load Balancer의 용도로도 사용되며, 클라이언트의 요청을 받아서 내부 서버로 전달해주는 Proxy를 말합니다.
- rdbms를 사용하신 이유가 있나요?
- 프로젝트 진행 중 어려웠거나 발생했던 문제점
- 쿼리 측정
- 쿼리최적화 작업 시 쿼리를 측정하는 동안 첫번째 쿼리를 측정한 이후로 그 이후 쿼리부터 검색 속도가 매우 빨라지는 오류가 있었습니다. mysql의 쿼리 캐시를 끄더라도 자체에 있는 innoDB buffer 그리고 이미 디스크에서 메모리로 올라온 많은 데이터들이 있기때문이라는 것을 알게되었습니다. 이후 쿼리 측정 관련햐여 저희가 찾아보았고, innnoDB_buffer_pool의 사이즈를 최소화하면, 완전하진 않더라도 어느정도 비슷하게 측정 할 수 있다는 것을 알게 되었습니다.
- 정합성 vs 성능
- 쿼리 성능을 좋게 하더라도 SWR을 사용하여 정합성을 맞게 하려면 지금까지 불러온 모든 데이터들을 다시 요청해야 했기 때문에 속도가 느려지는것을 확인했고 정합성과 성능에서 고민하였습니다. 이번 프로젝트에서는 정합성을 택했습니다. 허나 최근에 가상스크롤로 이를 구현하면 두마리토끼를 잡을 수 있을것 같아서 공부해볼 예정입니다.
- 저희팀은 사는곳이 수원에서 포항까지 있었기 때문에, 프로젝트 진행중에 100% 온라인으로 진행하였습니다. 그랬기 때문에 서로친해지는 것이나 소통하는 것이 처음에는 많이 어려웠습니다. 이를 해결하기위해 서로 말을 놓기로 했고, 첫주차에는 잠깐 게임을 하는 등 아이스 브레이킹을 진행하였습니다. 이제 많이 친해져서 다들 프로젝트에만 더욱 더 몰두 할 수 있었고, 이제 다음주 중으로 한번 만날 예정입니다.