전체 글 342

[SQL] ANSI Join

SQL 문법을 공부하던 도중, 대부분의 문법은 비슷하지만 MySQL과 Oracle에서 사용되는 구문에서 조금 차이가 있다는 점을 알게 되었다. 그럼 각각의 데이터베이스에 대한 구문 정보를 모두 알아야 하나? 물론 모두 알아두면 좋겠다만, 조금 비효율적이라는 생각이 든다. 또한 MySQL로 작업하다 Oracle로 DB를 변경해야 하면 다 찾아서 변경해야되는데 여간 번거로운 일이 아닐 것이다. ANSI 조인은 위와 같은 상황에서 아주 유용하게 쓰일 것이다. ANSI 조인이 뭔데? ANSI 조인은 데이터베이스에서 테이블을 결합할 때 사용되는 표준 SQL 문법 중 하나이다. 이러한 조인은 명시적으로 조인 조건을 정의하여 테이블을 연결한다. SQL 표준이기 때문에 여러 데이터베이스 시스템에서 지원된다. 그러니까 ..

개발 일지/SQL 2023.08.01

Queue 자료구조에서 add와 offer의 차이

Java에서 Queue 인터페이스를 사용하는 도중 add와 offer는 같은 동작을 하는 것 같은데, 왜 분리되어 있는 걸까? 라는 생각이 들었다. 보통 Queue는 LinkedList 자료구조를 활용하기 때문에 LinkedList 에서는 어떻게 구현하고 있는지를 확인해봤다. ..? 소스 코드로 구현 원리를 파악할 수는 있지만 offer도 결국 add를 사용하는 것처럼 보였다. add와 offer가 분리된 명확한 이유를 모르겠어서 구글링의 단계로 돌입했다. add와 offer의 차이 우선 'add'와 'offer' 모두 요소를 컬렉션에 추가하는 데 사용된다. 그럼 차이는 뭘까? 'Collection' 인터페이스에서 'add' 메서드의 반환 값은 항상 'true'이다. 따라서 Queue 인터페이스를 구현한..

개발 일지/etc 2023.07.31

[Java] serialVersionUID

Java에서 serialVersionUID는 직렬화(serialization)와 관련된 필드이다. 직렬화는 객체를 바이트 스트림으로 변환해서 저장하거나 네트워크를 통해 전송하는 과정을 말한다. 이렇게 직렬화된 객체는 나중에 역질렬화(deserialization)해서 원래 객체로 복원할 수 있다. 하지만 클래스의 구조가 변경되거나 버전이 업데이트된 경우에 문제가 발생할 수 있다. 이 때 'serialVersionUID'를 사용해서 객체 버전을 명시적으로 관리하는 것이다. serialVersionUID의 목적 serialVersionUID는 직렬화된 객체의 버전 번호를 나타낸다. 객체가 직렬화되면 버전 번호가 함께 저장되며, 역직렬화될 때 같은 버전 번호를 가진 클래스로만 역직렬화가 가능하다. 이는 클래스의..

개발 일지/Java 2023.07.29

SQL 공부의 필요성

학습 이유 그동안 Spring Boot 기반의 프로젝트를 진행하면서 JPA를 사용했기 때문에 별도로 SQL문을 작성하지 않아도 데이터베이스 조작이 가능했다. 또한, 프로젝트에서 기본 CRUD에 대한 작업만 진행했어서 JPA의 한계점이라던가 SQL 문법의 필요성을 느끼지 못했던 것 같다. 하지만 프로젝트 기간이 끝나고 유지보수를 위해 코드를 살피는 도중 N+1 문제가 발생하는 것을 확인했고, 주요 도메인에는 1:N 관계의 테이블이 많아서 (구글링하면 나오는 일반적인 방법들)fetch join이나 @EntityGraph로는 해결할 수 없었다. 그래서 QueryDSL을 공부해서 해결하려고 생각중이었다. 그리고 JPA는 편리한 기능을 제공하긴 하지만 대량의 데이터를 처리하거나 복잡한 쿼리를 실행하기에는 한계가 ..

개발 일지/SQL 2023.07.14

2023 토스 NEXT Server 직무 코딩테스트 후기

부트캠프를 수료하고 이제 막 취업 준비를 시작하면서 맞이한 첫 코딩테스트.. 설렘 반 긴장 반으로 응시하고 왔다. 작년과 재작년에 진행된 NEXT 후기를 많이 찾아봤는데, 코딩테스트 7문항(90분) + 서술형 5문항(30분)으로 이루어져 있고 완전 타임어택 형식으로 진행되어서 그런가 코딩테스트 문제는 다른 기업들에 비해서 쉽게 나왔다고 했다. (백준으로 실버 이하?) 하지만 서술형에서 진짜 개발을 하면서 접할 만한 문제들이 나왔고, 거기서 애를 먹은 분들이 많아 보였다. 이번 시험도 마찬가지로 코딩테스트 7문항, 서술형 5문항으로 프로그래머스 플랫폼을 통해 진행되었다. 실제 코테가 진행되기 전에 모의테스트 메일이 2번 오는데, 첫 번째 메일에서는 앞서 진행한 테스트와 같은 방식으로 진행된다고 했지만 두 ..

카테고리 없음 2023.07.08

[백준] 21736번

int형의 2차원 배열(map)을 선언하고 다음과 같은 규칙을 통해 값을 넣어줬다. /* 0 : 빈 공간, 도연이 1 : 벽 2 : 사람 */ 그리고 도연이의 위치를 저장해두고 dfs(도연이의 y 좌표, 도연이의 x좌표)를 돌려서 해결! public class Main { static int[][] map; static boolean[][] check; static int[] dx = new int[]{0, 1, 0, -1}; static int[] dy = new int[]{1, 0, -1, 0}; static int N, M, peoples = 0; public static void main(String[] args) throws IOException { BufferedReader br = new B..

[JPA] N+1 문제에 대해서

위 로직은 이력서 도메인과 1:N 관계의 entity들이다. 1개의 이력서에는 기술 스택, 교육 사항, 프로젝트, 경력 등을 여러 개 입력할 수 있다. 여기서 하나의 이력서(CV)를 조회할 때, N+1 문제가 발생하는 것을 확인했다. 로그를 보면, 하나의 이력서(CV)를 조회하는 쿼리가 날아가고 추가적으로 연관된 객체들이 조회되는 것을 확인할 수 있다. 만약 여러 개의 이력서를 조회한다고 가정하고 이력서의 개수가 N개라면 N * (1 + 8)개의 쿼리가 발생한다. 극단적으로 예를 들면 10000개의 이력서가 있고 findAll()로 이력서들을 조회하면 90000개의 쿼리가 발생할 것이다. 따라서 1번의 쿼리에 N번의 쿼리가 추가 실행되므로, 쿼리 실행 횟수가 증가하여 성능에 부담을 주고 데이터베이스에 부..

Service 로직에서 List를 다룰 때 발생하는 index 문제 해결

프로젝트에서 맡은 이력서 CRUD 작업의 기본 로직을 다 만들어 두고 추가로 수정할 부분이 없나 하고 찾아보다가 문제를 하나 발견했다. Postman으로 여러 데이터를 입력해보고 테스트를 진행했을 때는 발생했던 오류가 아니어서 작업하면서는 찾지 못했던 것 같다. 기존에 작성했던 코드는 다음과 같다. 이력서를 수정하는 코드 안에 포함된 로직이다. 이 로직을 추가한 이유는 사용자가 이력서를 수정할 때, 기존의 이력서에는 경력사항이나 프로젝트 등이 들어가 있었지만 해당 데이터들을 지우거나 수정한 경우에 수정된 이력서에 들어가 있는 경력 사항 등만 두고 기존의 데이터는 지우려고 했기 때문이다. 테스트를 할 때는 저 로직에서 발생하는 예외상황을 생각하지 못했었는데, 위 remove에서 밑줄 그인 부분이 신경쓰여서..