728x90
반응형

백엔드 22

[썬카/백엔드] 차량 목록 조회 쿼리 작성 과정에서의 N+1 문제 발생과 해결

신뢰성이 중요한 중고차 거래에 필요한 차량 정보를 담기 위해서는 꽤 많은 테이블이 필요했다.차량 목록 조회 기능을 구현하는 것에만 5개의 테이블이 엮여있었고, 5개 테이블을 전부 조인해서 데이터를 가져와야 했다. 썬카는 차량 한대 당 메인 이미지 1개와 나머지 이미지들이 존재하며, 대표 이미지 여부는 is_primary 필드로 구분된다.메인 이미지는 가장 먼저 화면에 보여야 하기 때문에, 나머지 이미지들과 dto 별도의 필드에 담길 필요가 있었다.따라서 처음엔 메인 이미지를 조회한 후 나머지 이미지를 추가로 조회하는 방식으로 진행했었는데, 이 과정에서 N + 1 문제가 발생했다. N + 1문제- 최초 1번의 쿼리로 N개의 레코드를 조회한 후, 추가로 N개의 쿼리를 실행하게 되는 상황- 자동차가 10대라면..

[썬카/백엔드] Swagger를 이용한 API 명세서 도입

백엔드로써 프론트엔드와 협업하기 위해, 커뮤니케이션 비용을 줄인 효율적인 업무를 위해 API 명세서는 반드시 필요하다고 할 수 있다. 명확하게 정리된 API 명세서가 있다면 프론트엔드는 해당 자료를 참고하여 좀 더 수월하게 작업할 수 있고, 서로 엇갈려 불필요한 오류를 맞이할 일도 줄어든다.  1. 의존성 추가// build.gradledependencies { // 생략.. implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.0'} build.gradle에 swagger 사용을 위한 springdoc-openapi 의존성을 추가한다. 단 여기서 스프링 부트 버전과 openapi 버전이 반드시 호환되어야 한다.각 스프링 부트 버전마..

[썬카/백엔드] dotenv를 사용한 중요 데이터 환경변수화

# application.propertiesspring.application.name=suncar# DBspring.datasource.url=jdbc:mysql://localhost:3307/suncarspring.datasource.username=rootspring.datasource.password=0000spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.jpa.hibernate.ddl-auto=updatespring.jpa.show-sql=true# JWTjwt.secret=BTpHjyFDurb0PefLrKP+e4vKKwNCw+rUoMEpQjde7T6EzB9QjtoqC7MFVcHwbFPr+r4/OlR9ZiB5rpG0axOd4Q..

[썬카/정기 회고] 스프린트 1 종료

기능 명세서 단위로 봤을 때, 구현한 기능은 2개 뿐이다. 로그인 그리고 회원가입.무슨 이거 2개 만드는데 3주나 걸렸냐 싶겠지만, 진짜 오래 걸린 것 맞다. 처음 진행하는 개인 프로젝트다 보니 생각보다 기능구현 외에 할 일이 정말 많다는 것을 느꼈다.회사에서 잠깐 일을 했더라도, 전부 짜여진 코드의 틀 위에서 약간의 기능 추가와 수정, 관리 정도였고.. 아예 환경세팅부터 시작하는 것은 처음이었으니 그럴 만도 하겠다. 지난 3주를 돌아보면 나는 단 하루도 쉰 날이 없는데 왜 이렇게 지체되었을까 라는 의문이 든다.아침에 일어나 운동을 갔다오고, 밥 먹고 하루종일 컴퓨터 앞에만 앉아있는데 말이다. 뭐 예비군도 갔고, 가끔 술도 마셨고 그러긴 했지만 그건 큰 핑계가 되지 못한다. 3주는 너무 길다.기간이 지체..

[썬카/백엔드] Soft delete 구현과 Base Entity 작성 및 적용

중고차 거래 플랫폼은 가치가 큰 물건을 거래하는 만큼 신뢰성 있는 데이터가 중요하기에, 실제로 데이터를 삭제하지 않고 논리적으로만 삭제하는 Soft delete 방식이 적합하다고 생각했다. 실수로 데이터가 삭제되어도 쉽게 복구할 수 있기 때문에 데이터 관리와 안정성이 중요한 경우 적합한 방식이라고 할 수 있다. Soft delete- 데이터베이스에서 레코드를 물리적으로 삭제하지 않고, 논리적으로 삭제된 것처럼 표시하는 기술- 일반적으로 테이블에 is_deleted 등의 필드를 추가하여 삭제된 상태를 표시한다. Soft delete - 필요성- 안전한 데이터 관리 : 우발적인 데이터 손실 방지- 데이터 복구 용이성 : 필요시 간단히 플래그만 변경하여 복구 가능- 유연한 데이터 접근 : 필요에 따라 삭제된 ..

[썬카/백엔드] 예외 전역 핸들러 및 커스텀 예외 구현

비즈니스 로직에서 발생하는 모든 예외를 캐치하고 일관된 형태로 응답하기 위해서, 전역 핸들러와 커스텀 예외를 구현했다.예외 처리 로직을 비즈니스 로직으로부터 분리할 수 있고, 클라이언트는 일관된 형태의 예외를 응답받기 때문에 예외에 대한 처리를 유연하게 할 수 있게 된다.  예외 전역 핸들러(Global Exception Handler)- 애플리케이션에서 발생하는 모든 예외를 일관되게 처리하는 메커니즘- Rest api를 구현한 Spring Boot에서는 @RestControllerAdvice 어노테이션으로 이를 구현한다. 예외 전역 핸들러 - 필요성- 코드 중복 제거 : 각 서비스마다 예외 처리 로직을 반복할 필요 없음, try-catch 블록 최소화- 일관된 오류 응답 : 모든 API에서 일관된 형태..

[썬카/개인 회고] 썬카 프로젝트의 시작

시작 단계에서의 내가 지향하는 프로젝트의 방향성적은 기능을, 완벽하고 확실하게 구현하기다양한 상황을 고려한 예외 처리테스트 코드 작성실무에서 사용되는 코드와 최대한 비슷하게 구현하기유지보수성 생각하기재사용성확장성가독성 ( 코드 컨벤션, 주석, 변수명 등 )왜 개인 프로젝트를 시작했는가?나는 백엔드다.아직까지 개인 프로젝트를 한 번도 해 보지 않았다.한 번쯤은 프론트, 백엔드 그리고 프로젝트의 시작과 끝까지 모든 것을 혼자 해결하며 프로젝트 흐름을 이해하고 싶었다.그래서 개인 프로젝트를 하기로 결정했다.실무에서 많이 사용되는 RestAPI 방식으로 진행하고 싶었다.그래서 템플릿 엔진을 사용하는 SSR 방식이 아닌, Vue를 사용한 프론트엔드를 따로 분리하여 직접 작업하기로 했다.왜 중고차 거래 플랫폼인가?..

[스프링 부트3 백엔드 개발자 되기] 후기, 스프링 부트 교재

결론부터 말하면, 10점 만점에 4점이다. 스프링 부트를 시작할 다른 사람에게 굳이 추천하고 싶지는 않은 책이다. 책을 끝까지 완독 후 후기를 작성하려 했으나 다른 일정과 겹쳐서 마지막 Git 버전관리와 AWS 배포 부분은 읽지 못했다. 그러나 시간이 나더라도 굳이 다시 펼쳐서 끝까지 읽고 싶지는 않은 마음이고... 완독하지 못했더라도 가장 중요한 웹사이트는 끝까지 만들어 보았으니 짧은 후기를 쓸 정도는 된다고 생각한다. 독자의 수준이나 기초지식에 따라서 책에 대한 견해가 달라질 수 있으니 나를 설명하겠다. - 정보보안 전공, 보안과 관련된 지식과 네트워크, 서버, 웹 등 기초 CS지식정도 보유. - JAVA, Python 기초문법 숙지한 상태. - "개발"을 해본적은 한번도 없다. 개발 공부는 이 책이..

독서/IT 2024.01.15

스프링 입문 - 회원 서비스 테스트

회원 서비스 개발에 이어, 개발한 회원 서비스를 테스트할 차례다. 테스트를 수행할 MemberService에서, Ctrl + Shift + T를 누르고, Create New Test를 누른다. 그러면 이런 창이 뜬다. 테스트 클래스 이름도 본래 클래스 이름에 Test만 붙여서 자동으로 작성해 준다. 내가 테스트하고 싶은 메소드를 아래에서 체크해서 OK를 누른다. 그러면 이렇게 테스트에 필요한 틀을, 적절한 위치(경로)에 아주 쉽게 만들어준다. 일단 만들어진 테스트가 문제가 없는지, 현재 상태에서 바로 한번 돌려본다. 다행히 문제는 없다. 본격적으로 테스트 케이스를 작성해 보기 전에, 잠깐 MemberService로 가보자. 기존 코드를 변경해서, 이렇게 생성자를 통해 외부에서 리포지토리를 주입받도록 변경..

스프링 입문 - 회원 서비스 개발

도메인, 리포지토리를 만들었으니 서비스를 만들 차례이다. hello.hellospring.service 패키지를 만들고, service 패키지 아래에 MemberService 클래스를 만들자. 서비스는 리포지토리와 함께 동작해야 하니, 미리 만들어두었던 리포지토리 객체를 만들어 주자. 회원가입 메소드인 join이다. member 객체를 매개변수로 받아서 리포지토리에 저장하고, 저장한 객체의 Id를 리턴한다. 단, 중복된 name을 가진 회원은 가입할 수 없도록 검증하는 과정이 있다. 바로 밑에 선언해둔 validateDuplicateMember가 중복을 검사하는 메소드이다. name을 기준으로 리포지토리에서 회원을 찾아서, 해당 회원이 이미 존재한다면 "이미 존재하는 회원입니다" 예외를 출력하고 메소드는..

728x90
반응형