전체 글

회사에서 FastAPI + SQLModel 기반 프로젝트를 하고 있어 SQLModel을 공부했습니다. 공식문서 번역본에 가깝지만 나름대로 이해한 내용을 정리해봤습니다. 이 글은 sqlalchemy 2.0.4 버전을 기준으로 작성했습니다. SQLModel은 SQLAlchemy를 기반으로 동작하므로, 데이터베이스 연결은 create_engine에서 생성된 Engine 객체가 관리합니다.Engin은 커넥션 풀과 Dialect를 통해 애플리케이션에 전달되는 데이터베이스의 시작점입니다.DBAPI란?Python Database API Specification의 약자로, 모든 데이터베이스 커넥션 패키지에 대한 일반적인 사용 패턴을 정의하기 위해 파이썬의 PEP 249에 정의된 스펙입니다. DBAPI는 파이썬 애플리케..
· Springboot
MEETPLUS 프로젝트 당시 프론트에서 HTTP GET 요청을 했는데 CORS 오류가 발생했습니다. 클라이언트 모든 요청은 gateway를 통해 들어오고 있었고, Spring Cloud Gateway 서버가 gateway 역할을 담당하고 있었습니다.gateway에서는 MSA의 각 도메인 서버별로 구체적인 경로와 필터를 지정해 준 상태였습니다.그런데 왜 CORS 오류가 발생했을까요? 이는 preflight 요청때문이었습니다.preflight 요청이란, 브라우저가 서버에 요청을 보내기 전에 이 요청을 허용할지를 확인하기 위해 보내는 예비 요청입니다.preflight 요청이 발생하는 조건1. CORS 요청이 "단순 요청(Simple Request)" 조건을 충족하지 않는 경우단순 요청의 조건은 다음과 같습니..
· Springboot
spring boot 애플리케이션 환경설정을 Spring Cloud Config로 관리하고 있었습니다.환경설정 파일(ex. application.yml)은 github private repository에 저장하고 Spring Cloud Config가 애플리케이션 실행 시 맞는 환경설정 파일을 가져와 적용해줍니다. 그런데 환경설정을 수정할때마다 변경사항을 적용하기 위해 /actuator/refresh API 를 호출해야했습니다.이는 환경설정이 빈번하게 수정되는 개발기간에 상당히 귀찮았고, 게다가 MSA에서 여러 애플리케이션들의 auctuator API를 호출하는 것도 비효율적이었습니다. 요구사항은 다음과 같았습니다.1. 레포지토리에 push하면 자동으로 수정된 환경설정이 적용될 것2. 한번의 동작으로 여러..
· AWS
AWS ECR을 사용하게된 계기작은 프로젝트에서 CI/CD 파이프라인으로 github action을 사용하여 docker hub에 docker image를 저장했었습니다.그러다가 간헐적으로 이미지를 받지 못하는 일이 발생했습니다.docker hub 무료 계정의 월 200회 pull 제한에 걸려서 그런 것 같습니다.프로젝트는 최대 하루에 10번 배포했던 적도 있어서 docker hub를 사용하기에 부적합했습니다.그리고 docker hub는 private 레포지토리에는 1개의 이미지만 저장할 수 있었고, 이미 다른 이미지를 private 레포지토리에 저장했던 상태여서 public 레포지토리를 사용했습니다. 그래서 보안상 문제가 있었습니다. 장점 및 단점docker hub의 대안을 찾아보던 중, AWS에서 완..
· Spring batch
jdbc로 다중 데이터베이스를 설정하여 JPA에서 사용하는 방법을 소개합니다.spring boot 3.0부터는 @EnableBatchProcessing을 권장하지 않습니다. 이걸 쓰면 자동으로 등록해주던 빈들을 수동으로 설정해야합니다.이 글에서는 @EnableBatchProcessing를 사용하지 않습니다.이말고도 다른 방법이 얼마든지 있으니 참고만 해주시기 바랍니다.IDEA: intellij사용한 데이터베이스: postgreSQLspring batch 5.0.5 1. spring batch 메타데이터 데이터베이스 만들기데이터베이스 종류별로 spring batch schema를 만드는 sql이 있습니다.org.springframework.boot:spring-boot-starter-batch 의존성을 추..
· Next.js
React 렌더링과 Children PropReact에서 children prop을 올바르게 이해하고 사용하는 것은 불필요한 렌더링을 막는 핵심 최적화 기법 중 하나입니다.핵심 원리: React Element는 불변이다가장 중요한 전제는 **"React Element는 불변(immutable)"**이라는 것입니다. UI를 변경하려면 새로운 엘리먼트를 생성해 기존 엘리먼트를 대체해야 합니다. 즉, 리렌더링은 새로운 엘리먼트를 만드는 과정입니다.React는 리렌더링 시 이전 엘리먼트와 새로 생성된 엘리먼트를 비교하여 변경이 필요한 부분만 DOM에 실제 반영합니다. 이때 props가 변경되지 않았다면 해당 컴포넌트와 그 자식 컴포넌트의 리렌더링을 건너뛸 수 있습니다. children도 props 중 하나입니다..
· Next.js
parallel + intercepting 라우트병렬 라우트와 함께 사용하면 모달에 대해 다음이 가능합니다:모달 콘텐츠를 URL을 통해 공유 가능하게 합니다.페이지를 새로고침할 때 모달을 닫는 대신 컨텍스트를 유지합니다.이전 라우트로 가는 대신 뒤로 이동하여 모달을 닫습니다.앞으로 이동하여 모달을 다시 엽니다.로그인 후 쉽게 직전 페이지로 이동할 수 있습니다.app디렉토리의 layout에 병렬 라우트(slot)을 prop로 추가합니다.이때 prop 이름은 병렬 라우트 디렉토리 이름과 같기만 하면 됩니다.루트 layout에 병렬 라우트를 추가해야 페이지에 나타나고, props로 사용할 수 있습니다. // app/layout.tsx export default function RootLayout({ chi..
· Springboot
모든 GrammarBook에서 각 book마다 연관된 Grammar 개수를 조회하는 기능이 있습니다. 해당 코드는 다음과 같습니다.@Transactional(readOnly = true)public List getGrammarNumOfAllGrammarBooks() { List responseDtos = new ArrayList(); for (GrammarBook grammarBook : this.grammarBookRepository.findAll()) { responseDtos.add( GrammarNumOfGrammarBookDto.builder() .id(grammarBook.getId()) .name(grammarBook.getN..
· Springboot
사용자가 문법 퀴즈를 풀고 틀린 문제를 저장하는 테이블(UserGrammarStatus)이 있습니다. 이 테이블에서 한 사용자가 틀린 모든 문법 문제를 조회하는 기능에서 N+1이 발생했습니다. 해당 기능은 아래 메서드이며, 사용자 이름으로 SiteUser 테이블에서 id를 찾아, UserGrammarStatus 테이블에서 해당 id의 grammar들을 조회합니다. @Transactional(readOnly = true) public WrongGrammarsResponseDto getUserWrongGrammars(String userName) { Long userId = getUserIdByUserName(userName); List userGrammarStatuses = this.userGrammarS..
· Springboot
“자바 ORM 표준 JPA 프로그래밍” 책으로 N+1에 대해 공부했습니다. 이후 기존 조회 로직들을 다시 테스트해보니 N+1 문제가 발생하는게 생각보다 많았습니다. 그래서 이것들을 모두 해결했고, 시리즈로 엮었습니다. 다음 코드는 Grammar 1개를 조회할때 연관된 GrammarBook과 GrammarExample까지 조회하는 service 메서드입니다. public GrammarDto getGrammar(Long id) { Grammar grammar = getGrammarById(id); return GrammarDto.builder() .id(id) .sentence(grammar.getSentence()) .grammarBookName(grammar.getGrammarBook().getName(..
siwoli
siwoli