티스토리 뷰

 

행사 주최자분이 광고도 많이하시고 주변에서 많이 간다고해서 참여한 컨퍼런스였는데

 

여느 컨퍼런스가 그렇듯 좋은 세션이 있는가 하면 애매한 세션도 있었다.

 

세션은 다음과 같다.

 

 

나는 백엔드 개발자라 거의 서버 세션에 쭉 있었다.

 

한번만 개발자의 공허함 Part2 를 들었는데, 이 세션은 참여자가 유난히 적었다.

 

총 6개의 세션을 들었는데, 세션을 들으며 내용을 정리하고 짧게 후기를 써봤다..

 

에어프레미아는 왜 재개발을 하는가?

별로 특별하지 않았던 세션... 재개발의 이유는 너무 보편적인 이유였고 재개발 방식은 딱히 새롭지 않았다.
가장 궁금한 부분인 FE/BE를 나누면서 어떤 아키텍처를 선정했고 k8s가 들어갔는지 운영을 위해 어떤 모니터링을 구축했고, 어떤 기준을 갖고 분리했는지에 대한 이야기가 너무 짧거나 이야기가 없었다.
요약하면 외주 업체가 개발한 레거시 코드 관리가 어려워서 리팩토링을 했다인데.. 이 이야기에 너무 긴 시간을 투자하신 것 같다.
내가 생각하는 기술적 혁신이 핀트가 안맞았다는 것도 있었다. 코드 레벨에서의 혁신이 사업적인 혁신까지 발전할 수 있을까? 개인적으론 어렵다고 생각한다. 최근의 인공 지능의 혁신도 하드웨어의 혁신부터 시작됐다.

 

조금 늦어서 앞부분이 짤렸습니다...

 

에어 프레미아 공식 홈페이지에서 체크인 항공권 확인 일정 변경 등 공식홈페이지가 가장 큰 프로덕트이다.

 

에어 프레미아 항공사를 기술적으로 혁신하고 싶었는데 코드부터 문제가 있었다.


어떤 상태였나?

들어가서 막상 확인해보니 와 이거 어떻게해야하지 싶을 정도였다.

백엔드 관점에서보면 JSP기반으로 FE/BE가 혼재 -> 레거시라 지칭
각 항공사의 예약 DB는 개별 DB로 가지고 있는게 아니라 Navitaire라는 플랫폼을 사용하고 잇음 API를 통해서 운영...

경계가 불분명해서 누가 어디까지 커버해야하는가? 원인 파악이 모호함 
불필요한 시간 비용이 추가로 발생함 > QA, CS에서 확인 요청이 옴 > FE/BE에서 추적하다보니 누군지 반대편 문제였음 

 

중복 코드가 매우 많고, 스파게티코드로 만들어놓고, 아키텍처의 수준이 매우 낮다.

존재 이유를 모르는 코드가 많음 > 히스토리 문제인가? 실제로 동작하는 코드인가? 이해하기 어려운 코드들이 있다. 

그리고 이 코드들이 정말 정상적으로 동작하는가?

이 모든 것들로 인해서 버그가 너무 많이난다.


코로나 이후에 새로운 모델로 운항을 시작하려고 했으나 당시의 테크 수준은 너무 힘들었다.

기존의 구조는 너무 느림. 확장성이 너무 떨어지는 구조. 안정성도 취약. 
> 재개발을 통해 안정성, 확장성을 갖춘 코드로 혁신해보자


어떻게 전환했는가?

자바 -> 코틀린, FE/BE 코드를 떼어냄, 서비스 로직을 대부분 BE로 이동 코드 모듈화에 신경 씀
네비테어 API 호출 방식 구현을 재사용 가능하고 실수의 여지가 적고 구현이 쉽도록 리팩토링
api 커넥션 관리, 에러 체계 정립

FE(shuka) -> BE(onepoint) -> 네비테어/DB 연동

네비테어 API?
rest + graphql 둘다 제공하는데 일부는 rest, 일부는 graphql을 사용중이었음

네비테어 클라이언트를 만들어서 한군데서 관리하도록 함

- client로 만들어서 api 형식으로 관리

- 네비테어 커넥션 풀 관리.

- 리소스 낭비가 일어날 가능성이 높아서 위험포인트가 있었다.

- 빈으로 등록해서 커넥션 풀을 재사용할 수 있게만 해주면 된다.

 

에러 전달 체계?

에러 코드 도메인 별로 정의

 

정리

이 외에도 많은 작업을 했지만, 세션에 다 담지 못했다고 하셨음. 멀티모듈화도 했고 이에 따라 생산성도 올라가고 있다고 하셨다. 그러나 세션의 대부분이 너무 보편적인 방식이거나 외주 개발을 내부로 다시 끌어왔을 때 모두 한번씩 겪는 일에 대한 내용이었다. 

 

요약을 정리하면서 다시한번 읽어봤지만 네비테어 API를 리팩토링한 부분이 사실 클라이언트와 커넥션 풀을 관리하는 정도에서 끝나지 않았을텐데, 조금 더 엣지 포인트를 이야기 해줬으면 재밌었을 것 같았다. 

 

발표자분에겐 죄송하지만, 준비가 조금 부족해보였던 세션이었다.

 

올리브영 전시 영역의 꺾이지 않는 안전성

최대 동접 10만을 소화하는 !! 서버개발자라면 누구나 관심을 가질만한 세션.
전시 영역이라는 독특한 도메인에서 스파이크 트래픽을 다루기 위한 리팩토링 과정에 대한 이야기였다.
같이 들으신 분이 배민도 비슷한 구조를 가진다고 알려주셨는데, 기억해두면 언젠가는 인프라적으로 써먹을 부분이 있을 것 같다.
이 세션도 레거시를 리팩토링하는 과정이었는데... 전 세션과는 다른 방식으로 발표하셨고 그만큼 훨씬 좋았다.
연사자 분이 준비를 정말 잘하셨고, 발표 스킬도 인상깊었다. 개인적으로 정말 많이 배운 세션이었다.

 

1. 올리브영 온라인몰의 역사

오프라인몰에서 온라인몰로 성장, 모바일 앱도 출시

재고 유무 확인, 관심 매장 이벤트 유무 확인 등

 

2. 이커머스 전시영역의 주요 페인 포인트

전시 영역? 배너 등을 통해 시각적으로 소비자의 구매를 유도하는 방식

상품 카드를 구성하는데 다양한 카테고리가 필요하다.

상품 썸네일 이미지, 가격 정보, 상품 정보, 재고 카운팅, 리뷰 할인가, 프로모션 플래그 등등

이러한 컴포넌트가 수 백개 접근하는 사람이 수십만명이면 어떡함? TPS 급하락..

자주 접근하는 상품일수록, 많이 팔리는 상품일수록 실시간 정보를 제공하기 어려운 점도 있었다.

 

페이지 로딩시간이 3초이상이면 50%의 사용자가 포기하기 때문에 로딩 시간 단축이 중요한 페인 포인트였다.

 

3. 올리브영 온라인몰 레거시와 MSA 전환 여정

모놀리식 아키텍처에 다양한 문제가 발생.... 도메인 간의 커플링이 너무 심했다.

장애가 서로 전파됨. 복잡성 상승, 유지보수 비용 상승, 신뢰성 하락

 

레거시는 온프레미스 환경 

가용할 수 잇는 자원을 max로 확보해도 죽는 현상. 스케일 업/스케일 아웃의 어려움. 복잡도 상승, 관리 비용 증가

 

엔터프라이즈 레거시(계열사의 외주 개발의 문제)

히스토리 파악이 어려움 > 사이드 이펙트 파악이 어려움,  관리 비용 증가, 개발 효율성 하락

홈화며 로딩속도가 평균 3.37초로 사용성이 떨어짐

영향도 파악부터 통합테스트까지 몇개월. 개발생산성 저하. JSP 구조로 코드가 뒤섞여 관심사 분리가 어려움

고객의 불편함 증대.. CS의 쇄도

 

사용자의 경험이 최고다... 입소문을 타면 최고.. 제프베조스의 말

 

어떻게 개선되었는가?

모놀로식 > MSA로 전환

GNB 모던 아키텍처 전환 프로젝트 착수... MongDB, Redis 아키텍처 도입, 다양한 고가용성 전략 도입함

1. MSA 구조로 전환했을 때의 장점 인프라적 관점에서 다양하게 스케일아웃이 가능하게됨 > 유동성 있게 대응

2. 도메인 간의 디펜던시를 끊어냄으로서 장애 전파를 받지 않고 안전성 확보

3. RDB 부하를 줄이고 더 많은 읽기를 처리하기 위한 캐싱 레이어 추가 > 캐시 어사이드 패턴

 

성능저하의 대부분이 RDB 접근 영역에서 발생

예측하지 못한 트래픽, 슬로우 쿼리로 인한 cpu 스파이크 > 읽기 성능 향상을 위한 캐싱 도입이 필요했음

쿼리를 가볍게하고 조회 자체를 줄이는 방식을 모색

레디스는 키에 TTL을 지정해주는데, 대규모 데이터 환경에서는 TTL이 문제를 발생시킬 수 있음

캐시 스탬피드 현상이 발생한다. 

순간적인 RDB에 부하가 발생할 수 있다. 전시데이터를 사전에 가공하는 방식을 사용

 

배치를 통해 MongoDB 데이터를 레디스에 갱신하는 방식을 선택함

 

RDB는 새로운 뭔가가 생길 때마다 테이블이나 컬럼을 자유롭게 만들기가 어려움, 많은 공수가 들어간다.

 

왜 MongoDB 였는가?

배치를 통해 JSON 형태로 데이터를 관리... ?

스키마가 없음. 확장성이 뛰어남.. 스키마의 유연성이 다른 NoSQL에 비해 압도적임

동시성보다는 데이터 관리를 어떻게 할 것인가가 이슈였음 > 확장성이 더 많이 필요햇다.

 

전시 데이터 오류 최소화를 위한 버저닝 관리

정확도가 높은 컨텐츠를 제공하고 싶다.

MD가 올린 데이터는 Oracle DB에 저장이 되는데, Mongo DB에 미래 데이터를 미리 저장시킬 때 휴먼에러가 자주 발생함 > 문제가 발생하면 슬랙 알림으로 구성 > 성공할 경우 레디스를 구성해 캐시로 서빙

 

이 과정들은 이벤트와 status로 관리함

 

그리고 스크롤을 끝까지 내리는 비율은 9~18% 정도다.

정적 영역을 분리해서 캐싱, CDN 적용을 통해 더 빠른 접근이 가능할 수 있도록 구성

 

4. 올리브영 고객 경험을 위한 고가용성 전략

가용성 : 고객의 경험에 영향을 미치는 장애를 최소화

- 캐시서버에 문제가 발생했을 때 어느 것이 더 나을까? 서버가 죽는 것? 느리게라도 뜨는 것?

서킷 브레이커 도입으로 장애 전파 차단

Redis 서버에 문제가 발생할 경우 MongoDB로 접근하여 데이터 서빙, MongDB가 문제가 발생할 경우 오라클로 접근 할 수 있도록 대응, 세일 처럼 많은 데이터가 들어올 경우 사용하지 않는 리소스를 OFF 해둠

 

홈 평균 응답속도가 99% 개선, 웹 성능 지표 최대 87% 개선

 

올영 세일마다 증가하는 트래픽에도 꺾이지 않는 안정성 !

 

5. 꺾이지 않는 안전성을 위해 잊지 말아주셨으면 하는 것들

- 레거시는 회사가 살아남았다는 증거입니다.

- 철저한 단위 테스트 수행, 일관된 코딩 컨벤션, 코드리뷰 등 품질향상을 위해 끊임없이 노력하세요.

- 안정적인 시스템 구축에 대한 해답은 단순히 기술에 있지 않습니다.

 

정리 : 개인적으로 만족했던 세션.... 내가 하고 싶은 일이 이런 것들이란 것도 다시 확인할 수 있는 기회였다.

 

꽤나 어려운 내용들도 있었는데, 알기 쉽게 정리도 잘해주셨다. 그리고 짬이 느껴지는 그런 내용들도 숨어있었다.

 

그만큼 깊이있는 발표 내용을 잘 정리해 주신 것 같다.

 

개발자의 공허함 Part2 : 완성 미완성 그리고 현재 진행형

짧은 강연과 질의로 이뤄진 세션이었는데 가장 가려운 곳을 긁어주지는 못 했다.
그래서 어떻게 해야하는데? 에 대한 결론이 없었고, 강조하지 않았다? 보니 사람들의 질문이 대부분 비슷했다.
질문들이 제가 xx한 상황인데 어떻게 해야하나요? 로 귀결됐다.
이런 질문들에 대한 답은 보통 있다. 본인이 그렇게 안하고 있을 뿐.... 어떻해야겠나요... 더 열심히 해야지
API 자동화 테스트 세션을 놓친게 아쉽게 됐다.

 

개발자로 성공하고 싶다면... 돈에서 자유로워야 한다

 

공허함 ? 허전함, 찝찝함... 사실 난 공허함은 별로 안느낌 > 할게 이렇게 많은데?

충만함 ? 치열함, 정성껏, 영혼을담아, 100% .... > 이런 건 지속가능성이 떨어진다. 페이스 조절이 필요함

 

외적동기 : 시간간극, 보상적 한계, 역효과, 스트레스, 번아웃

내적동기 : 즐겁게, 만족감, 충만함, 뿌듯함

 

외적동기를 이기는 내적동기를 만드는게 중요함

 

목표는 나를 일상을 충만하게 하진 못한다.

목표를 달성하기 위해, 쏟아부을 것인가? 과정의 결과로 목표를 이룰 것인가?

> 작은 목표를 빠르게 이뤄가자. 성취를 하고 학습을 하다보면 언젠가 목표는 달성이 된다.

 

과정의 중요성

많은 시행착오가 있기 마련. 완성이 있나?

계속 고도화되고 발전하기 때문에 진행 중임... 하지만 특정 시점에 대한 완성은 있다.

 

겉핥기에 빠지지마라

경험이라는 과정을 통해서 본질까지 얻어왔는가? 철학이 무엇인가?

모든 현상에는 Time, Place, Ocaasion이 필수다. 기회를 잡기위한 때를 놓치지마라.. 

 

정리: 일단 난 공허하지 않아서 그런지 그렇게 인상깊지 않았다. 쉬어가는 세션이라고 생각하고 들었는데 그래도 아쉽다..

 

연사자분이 질문에 대한 답변을 본인이 겪으신 일들을 경험을 기반으로 답변을 해주셨는데, 사람들이 정말 깨우칠 정도의 임팩트 있는 답변이었나? 하면 그건 아니지 싶었다. 

 

100명의 개발자분을 도와 100개가 넘는 오픈 소스 PR을 함께 만들고 세상을 바꾼 이야기

4월에 인제님이 연사로 참여하셨던 오픈소스 멘토링에 참석했었다. 그때, 자신의 분야가 아니어도 가이드를 해주시는 모습을 보고 정말 대단하다고 느꼈다. 세션 후 다음 날에도 멘토링을 진행하시는 걸 보니 체력도 대단하신 것 같았다.

세션 후 내 상황(메인테이너가 리뷰를 너무 드문드문 해주는 경우와 내 기여를 무시하고 진행해버리는 일)에 대해
짧게 대화를 나누었는데, 이에 대해 인제님은 자주 있는 일이니 다른 것도 천천히 해보는 게 좋다고 조언해주셨다. 개발자로서뿐만 아니라 모든 면에서 귀감이 되시는 분이라는 생각이 들었고, 나도 언젠가는 많은 사람을 돕고 싶다는 생각을 하게 됐다.

 

 

오픈소스 기여를 시작하다

오픈소스 기여, 여러분은 막막하지 않으신가요?

- 50% 개발자가 관심은 있지만 못하고 있었음 2만6천명 대상

- 우리나라는 개발자의 22% 정도만 기여하고 있어서 안타까웠음

- 삶의 우선순위로 인해 어려움

 

100명의 오픈소스 기여를 돕다

첫 PR을 만들기 위한 물리, 심리적 장벽이 있음

- 코드 스타일은 어떻게 하지?, 어디에 어떤 코드를 추가하지? 심리적 저항

 

국내 오픈소스 기여가 왜이리 적을까?

- 막막함, 자극을 받고 도움을 주고 받을 기여자 자체가 많이 없음, 공유하고 자랑하고 돕는 문화 부족

- 애초에 오픈소스 기여는 누군가의 도움을 받아서 시작하는게 아닐까?

- 금,토,일 3일만에 PR을 만드는 멘토링을 시작하게 됨

- 이슈 선정가이드와 실제 어떻게 해결해가는 과정을 공유

 

국내 오픈소스 기여를 공유하는 문화를 만들다

- 기여 과정을 notion에 정리하고 있음

- 오픈소스 기여 과정이나 프로젝트 빌드 방법등을 링크드인이나 블로그 등에 공유하게 됨 

- 언젠가는 글로벌 오픈소스를 만들거나 책을 만들려고 함

 

정리 : 중간 중간 내 이름도 나오고 내가 기여한 레포도 나와서 흐뭇했다. 한동안 오픈소스에 대해 놓고 있었는데, 다시 한번 찾아봐야겠다는 의욕이 되살아났다.

 

DB를 느리게 만드는 다양한 방법들!

데이터베이스를 공부해야지해야지 미뤄뒀던 걸 후회하게 만든 세션. 마지막 사례를 정리해 준 내용들은 난이도가 제법 높았다. 막바지에 연사자 분도 사람들이 멍하니 보는 것 같아보였는지 급하게 마무리하셨다. 가장 난이도가 높았지만 얻어간 것도 많은 세션이었다. 언젠가는 도움이 될만한 많은 키워드들을 얻은 것 만으로도 가치가 있었다.

 

왜 내가 만든 쿼리는 항상 느릴까? How to make slow my query?

SRE : 회사 서비스의 안정성을 보장하고, 영속성을 보장한다.

A라는 팀에서 발생한 에러가 B에 영향을 미쳤는데, A 서비스는 문제없이 동작하는 경우 이런 문제를 관장함

 

튜닝은 엣지케이스니 주의가 필요하다. 절대 바로 적용하려하지 말 것

 

문제를 바르게 인식하기(지금 있는 문제가 DB의 문제가 아닐 수 있다)

- 비즈니스에 대한 이해  : 반드시 그시간에 실행되어야 하나?

- 슬로우 쿼리를 튜닝하기 : 다른 쿼리에 의한 대기 상태가 더 많이 발생한다.

- 최적화 이해 : DB에 대한 이해가 높아야 함. DB와 같은 사고방식을 가져야 함

 

데이터베이스는 대부분의 시스템에서 엔드 포인트를 담당하고, 장애가 전체로 확산되기 때문에 주의가 필요하다.

 

장애를 사전에 예방할 수는 없을까?

> 코드 리뷰, 테스트 강화, 모니터링, 이중화 등으로 대비한다.

 

쿼리가 느리다는 것을 어떻게 판단하나요?

> 응답속도? 실행 계획 분석? 느리다고 하니까? 느낌으로? .. 느낌으로 DB의 문제라 생각하는 경우도 잦다...

 

그러니 문제를 명확히 파악해라....

DB 성능을 이야기 할 때에는 순수 DB 관점에서 파악하고 DBA 관점에서의 응답 속도는 DB 서버에서의 응답이다

> 다행히 DB는 SQL만 봐도 성능 예측이 가능하다...

이미 쌓여있는 데이터를 알고 있고, 사용자 패턴도 알 수 있기 때문이다.

 

ORM이 알아서 해주는데 쿼리를 알아야 할까?

아직까지 100% ORM이 커버하진 못한다. 객체 모델과 관계형 모델 간에 불일치가 존재하기 때문에 알아야 한다.

 

쿼리 분석을 어떻게 해야하나?

1. FROM > WHERE > ON > SELECT > 그외 나머지

2. 테이블 정보를 수집

- 스키마 정보와 인덱스를 확인 : where절, on절에 사용된 키가 인덱스에 있는지 확인, select에 사용된 컬럼이 인덱스에 포함되어 있는지 확인(커버링 인덱스)

- 제약 조건 확인

- 컬럼의 속성 확인 : 조회하려는 컬럼의 길이가 얼마인지 확인

- 데이터 확인

 

테이블 크기가 크면 64테라가 너믄다.... join을 잘못하면 며칠씩 락이 걸릴 수도 있으니 매우 조심해야 한다...

 

인덱스 기초 이해

클러스터 인덱스 

- MySQL에서 기본적으로 사용

- PK는 인덱스가 아님

- B-Tree를 사용하고 모든 데이터는 리프 레벨에서만 저장

- 고유 컬럼이면 UNIQUE 인덱스로 생성할 것 권장. 유니크 설정이 안되있으면 uniquefier 정보를 추가로 저장 하게됨

- 키 값으로 정렬된 넓은 범위 검색에 유리.

- 테이블 당 1개 인덱스 생성 가능(왜? PK 특징은 정렬. 정렬 기준을 여러개 넣을 수 없다)

 

운영 중에는 인덱스를 함부로 건드리면 안됨.

클러스터 인덱스는 정렬을 하기 때문에 물리적 이동이 발생한다. 락이 발생한다!! 인덱스가 잠기면 테이블 자체가 잠겨버린다 ㅠㅠ 모든 데이터가 잠기기 떄문에 조심해야한다.

 

non-클러스터 인덱스

- 테이블과 별개로 인덱스 키로만 구성된 별도의 B-Tree 인덱스 영역 생성

- 테이블 구조에 따라 인덱스 구조가 조금 다름 

- 별도의 인덱스 페이지를 만들어서 관리하기 때문에 운영 중에서 만들어도 상관 없음

- 논 클러스터 인덱스는 힙을 사용함

- 클러스터 인덱스가 있을 때 논 클러스터 인덱스를 만들 땐 순서가 중요해진다.

- 클러스터를 만들고 논클러스터를 만들어야한다.

- 클러스터 인덱스를 만들면 재정렬이 되기 때문에, 논클러스터를 먼저 만들면 다시 주소를 갖는 테이블을 재생성해야한다. > 모든 스키마가 잠김...

 

인덱스의 크기가 중요한 이유

인덱스는 8192 Byte. 인덱스 깊이가 깊어질수록 성능에 영향을 받음. B-tree는 로그 단위의 복잡도, 키의 크기가 작을수록 페이지당 밀도 높아 검색 효율이 높음. 설정되는 컬럼의 크기가 작아야 효율성이 높다...

 

다양한 사례를 통한 튜닝 전략

RDB에서 컬럼의 순서는 중요하지 않다. 쿼리 파서는 SQL 문장을 잘게 쪼개서 서버가 이해할 수 있는 수준으로 분리하여 트리 형태로 구조를 생성한다. 성능과 아무런 관련이 없어!!

 

쿼리 파서의 동작도 오버헤드다. 그래서 쿼리는 재사용하는게 좋다.  스토어드 프로시저 등을 이용해서 재사용한다.

 

옵티마이저가 컬럼 순서를 가~끔 잘못 해석할 때가 있는데, 힌트를 줘서 순서를 지정할 수 있다.

 

그러나 이런 경우는 너무 엣지케이스니 고려하지 않아도 된다.

 

최적 경로 찾기

옵티마이저는 쿼리를 가장 저렴한 비용으로 가장 빠르게 처리할 수 있는 방법을 결정하는 담당한다.

SQL의 파싱 정보를 확인하여 어떤 테이블을 읽고 어떤 인덱스를 읽을 것인지 선택 - 최적화 및 실행계획 수립 단계

 

쿼리 플랜 생성

대부분 옵티마이저가 선택하며, 옵션과 힌트로 사용자가 더 나은 선택을 할 수 있도록 유도 가능

그러나 옵티마이저가 언제나 최적의 경로를 선택하지 않는다. 그냥 괜찮은 걸 선택하고 제안해준다. 이게 실행계획이다

최적의 경로가 필요한 경우 때문에, DBA가 튜닝을 하는것

 

사례 정리

반드시 필요한 컬럼만 조회한다.

- lookup 최소화

- lookup은 인덱스에 없는 컬럼의 데이터를 조회하기 위해서 실제 데이터 페이지에서 데이터를 조회하는 과정

- lookup은 인덱스 페이지의 주소값을 이용한 랜덤 액세스 방식으로 실제 I/O 비용이 많이 발생한다.

 

복합 인덱스(복합 키)는 컬럼 순서가 중요하다.

- 두 개 이상의 컬럼을 키컬럼으로 사용

- 선행 컬럼에 따라 성능 차이가 크다. 선행 컬럼으로 Seek 여부를 결정

- 복합 인덱스여도 트리 높이가 동일하면 검색 속도가 동일하기 때문에 선행 컬럼의 여부가 중요하지 않다.

 

형변환 주의(컬럼의 가공)

- 데이터 타입 불일치로 암시적 형변환 발생시 인덱스 사용할 수 없음

- 동일한 데이터를 저장하는데, 스키마의 크기가 다른 경우 의외로 성능이 느려짐

- ISNULL, SUBSTRING보다는 앞에 뭔가 있을 경우에는 차라리 LIKE를 써라

 

부정 조건은 긍정 조건으로 최대한 변경하여 사용

- 기본적으로 RDBMS는 부정조건은 인덱스를 활욯아지 못함

- 인덱스는 조건에 맞는 것을 찾는 것에 초점이 맞춰져 있기 때문, 부정 조건은 조건외 나머지 모두를 뜻하기 때문에 전체를 다 읽어야만 알 수 있어

- NOT IN, != 보다는 OUTER JOIN으로 NULL 검색으로 치환해라

 

데이터 존재 유무 판단을 하는 다양한 방법

- 데이터 존재 유무를 판단할 때는 목적에 따라 사용 쿼리가 다름

- EXISTS를 써라. 1행이라도 검색되면 TRUE로 판단하고 종료하기 때문이다.

- TOP 1(LIMIT 1) :  조건에 맞는 행을 읽고 1행을 반환함 > 비효율

- COUNT  사용 XXX

 

UNION ALL과 UNION 차이점 이해

- 두개 이상의 결과를 합쳐서 보여줄 때는 UNION 또는 UNIONALL 사용

UNION : 데이터를 합쳐서 보여줄 때 중복을 제거하고 반환

UNION ALL을 써라

 

불필요한 정렬, 그룹화는 성능을 느리게 만든다.

- 정렬에는 많은 리소스 비용이 소모, 반환되는 결과가 작다고 쿼리비용이 적게 드는게 아니니까 주의

- 정말 필요한 경우가 아니라면 정렬ㅇ르 수행하지 않는 것이 조음

- 정렬할 때는 최대한 많은 인덱스를 활용할 수 있도록 유도

 

조인은 약이 되기도하고 독이 되기도 한다.

- 조인은 두 개의 다른 테이블을 합쳐서 사용할 때 필요한데, 첫 테이블을 작게 가져가는게 매우매우 중요하다.

 

사용자 함수는 정말 주의해서 사용

- row 수만큼 함수가 호출되어 실행되기 때문, 결과 row 수만큼 새로운 쿼리가 실행된다보면됨

- 최대한 결과 행을 작게 만들고 나서 함수를 사용할 것을 ㅜ건장

- 옵티마이저가 효율적인 실행 계획을 만들기 힘들다...

- 수행 횟수 최소화 or 함수 내부 최적화 중요...

 

서브 쿼리는 정말 느릴까?

- 스칼라 서브쿼리만 느림. 함수처럼 동작함 select 서브쿼리만 느리다는 뜻

 

효율적인 인덱스 전략

- lookup을 최소화해라 정말 큰 성능효과를 볼 수 있음

  : 데이터가 작을 때는 티가 안남

 

정리하면, DB 튜닝은 지속적으로 이루어져야한다.... 튜닝의 끝은 모델링이다. 모델링만 잘되도 좋다....

 

정리 : DB는 언제봐도 어렵다. 공부를 더해야겠다 ㅠㅠㅠ.. 그래도 이번 세션이 미래에 많은 도움이 될거라 믿는다.

 

연사자분도 사람들이 어려워하는게 느껴지셨다고 한다. 그래서 빨리 마무리하심...

Spring AI 입문하기 with gemini

오픈소스 멘토링 오픈카톡방에 있는 종훈님이 발표하신 세션. 이 레포에 기여하고 싶기도하고 사용법도 알아두면 좋을 것 같아서 듣게 됐는데, 생각했던 것보다 많은 걸 배웠다. RAG의 사용법, Vector Store의 의미와 필요성 등등 사전 지식이 있고, AI 서비스를 사용하는 사람이라면 꽤나 유익했을 세션이었다.

 

Spring AI 소개

LLM을 사용하여 애플리케이션 생성을 단순화하도록 설계된 프레임워크

LangChain과 LlamaIndex와 같은 파이썬 프로젝트에서 영감을 얻어 진행된 Spring 프로젝트

(하지만 직접적인 포팅을 목표로하진 않는다)

 

그동안 AI 분야에서의 자바의 역할은 거의 없었음 ㅠㅠ

그래서 HTTP를 통해 미리 훈련되 모델과 상호 작용할 수 있게 되었다. HTTP는 스프링의 전문분야다!

 

AI 핵심 용어 설명

생성형 AI : 텍스트 이미지 및 다양한 컨텐츠를 사전훈련된 모델로 생성해낼 수 있는 AI

LLM(Large Language Models) : 대규모 언어 모델, 방대한 양의 데이터를 학습하여 자연어 및 기타 유형의 콘텐츠를 이해하고 생성하여 광범위한 작업ㅇ르 수행할 수 있는 모델

프롬프트 : AI 모델이 특정 출력을 생성하도록 유도하는 언어 기반 입력 (!= 입력창에 입력한 텍스트)

 

검색 증강 생성(RAG, Retrieval-Argumented Generation)

추가적인 데이터로 LLM 지식을 증강하는 기술. LLM은 광범위한 주제에 대해 추론할 수 있찌만, 훈련 받은 시점까지의 데이터에만 국한되기 때문에 아쉬움.

 

모델이 비공개 데이터나 최신 데이터에 대해서 추론 할 수 있게하려면?

모델에 필요한 특정 정보로 모델의 지식을 증강, 적절한 정보를 가져와 모델의 프롬프트로 삽입하는 프로세스를 RAG라 함

 

인덱싱 과정 : 데이터를 데이터베이스에 적절히 저장합니다. Retrieval and generation 사용자 입력이 AI 모델로 전송될 때 유사한 문서세트를 검색합니다. 사용자 입력과 함께 AI 모델로 전송됩니다.

 

이 외에도 AI, 모델, 토큰 등등을 설명해주심

 

어떻게 해야 검색을 잘 되게 할 수 있을까요?

- 임베딩을 사용하자 > 텍스트를 벡터로 변환하는 과정

- 벡터 유사성을 이용해 가까운 거리에 위치한 임베딩 데이터를 찾음

- 벡터 유사성은 의도한대로 동작하지 않을 수 있으니 유의해야한다. ex) korea, cuba

- 키워드 기반 검색에서 벗어나 의미 기반 검색으로 검색할 수 있게 된다.

 

벡터 데이터베이스 : 데이터 파일을 검색해서 모델로 전송함

환각 : AI 모델이 부정확하거나 오해의 소지가 있는 결과를 생성하는 것을 의미, 여러가지 이유가 있을 수 있음

 

Spring AI 프로젝트를 Gemini를 사용해 초기화하는 법

Chat Model API - Gemini를 검색

google에서 gemini를 생성하고 vertex ai를 설정하고 credential도 발급받아야 함.

토큰 제한 - 컨텍스트 윈도우 - 이 제한을 초고하는 텍스트는 처리하지 않고 gemini는 1 milion : 꽤 큰 양임

 

포켓몬 검색 LLM을 만드는 과정

- 포켓몬 검색에서 할루시네이션이 발생하는 것을 알아냄

- poke API의 존재 확인 후 데이터 가공(노가다)

- ETL 파이프라인을 구축

- 벡터 데이터베이스 milvus를 사용

- vertex ai 연동하는 걸 메인테이너가 만들어놨음

- 그런데 gemini api에서는 embedding model이 다국어 모델을 지원하지 않아서... openai 임베딩 모델을 사용

- spring ai는 auto coinfiguration을 멀티 벤더 문제가 발생해서 사용하지 않는 api를 disable해야함

- vector store embedding 차원 수가 문제가 있음... milvus와 spring ai, openai의 embedding vector의 차원수가 다 다름

> 차원 축소를 이용해서 해결

 

하지만 레퍼런스가 없었고, 굳이? 란생각이 있음. 비용적인 문제도 있었다. 그리고 gemini나 spring-ai가 빠르게 변하고 있어서 쉽지 않음

 

정리 : fine tuning 없이 RAG으로 모델을 개선해 나간다는 의미를 알기 어려웠는데, RAG 부분을 알기 쉽게 잘 설명해주셔서 큰 도움이 됐다. 그리고 Azure Java SDK의 Open AI 부분을 분석하면서 Vector Store가 왜 나오는지 이해가 잘 안됐는데, 이것도 자연스럽게 알게 됐다.

 

Spring AI를 어떤 경우에 어떻게 써야하는지 애매했는데, 적절한 어플리케이션을 만들어가는 과정을 설명해 주시면서 가이드 해주셔서, 쉽게 이해할 수 있었다.

 

마치며

좋은 세션도 있었고 애매한 세션도 있어서 생각보다 별로였다 이야기하시는 분이 많았다.

 

학생들이 듣기에는 어려운 세션도 있었고, 특히 FE 분들이 세션 구성에 많이 아쉬워하셨다.

 

나보고 세션 준비를 하고 발표를 잘했겠냐고 물었으면 그건 아니었겠지만...

 

이건 유료세션이었다... 조금 더 준비가 잘되었으면 좋았겠다는 생각이 들었다.

 

그러나 BE 개발자 입장에선 상당히 알찬 구성이었고, 테스트 세션을 놓친 것 말고는 잘 챙겨들은 것 같다.

 

그리고 정말 여러 사람들을 만났는데, 모든 사람들과 이야기를 오래 못 나눈게 아쉬웠다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
글 보관함