전체 글
나의 삶의 지도
되돌아보기 군대를 전역하기 전까지는 딱히 꿈이 없었다. 고등학생 때는 그저 수험생활에 충실했고, 대학교에 들어와서는 연애도 하고 술도 먹는 평범한 대학생이었다. 1학년 1학기가 끝나고 반수를 하긴 했지만, 그 선택 역시 뚜렷한 목표가 있어 한 것은 아니었다. 단지 지금보다 높은 레벨의 학교에 가려고 선택한 수험생활이었고 보기 좋게 실패했다. 군대는 의무 소방으로 다녀왔는데 크게 힘든 것은 없었다. 남들처럼 전역날을 바라보며 하루하루를 보내고 있었다. 그러던 어느 날 TV에서 우연히 알파고와 이세돌의 경기를 실시간으로 보게 되었다. 바둑에 문외한인 나였지만 그 경기를 보며 세상이 크게 변하고 있다는 사실을 실감했다. 그리고 그날 밤새도록 알파고와 딥마인드에 대해 검색해보며, 딥마인드가 어떻게 인공지능을 학..
Lombok 정리
@Getter와 @Setter, @RequiredArgsConstructor와 같이 기본적으로 사용하는 애노테이션에 대한 설명은 생략한다. @FieldDefaults Adds modifiers to each field in the type with this annotation. Complete documentation is found at the project lombok features page for @FieldDefaults. If makeFinal is true, then each (instance) field that is not annotated with @NonFinal will have the final modifier added. If level is set, then each (inst..
💻2022년 회고록
올해의 시작과 끝은 우아한테크코스였다. 작년 3월부터 다녔던 광고 대행사를 1월에 퇴사하고 우아한테크코스를 시작했다. 지난 1년 동안만큼은 어느 다른 해보다 시간을 압축적으로 보냈다고 자부한다. 대상포진에 걸리다. 그동안 회사 생활과 개발공부를 무리하게 병행한 탓에 몸이 많이 쇠약해졌다. 그래서 우테코를 시작하기 전 1월 말에 나는, 대상포진이라는 무서운 병에 걸렸다. 대상포진 균이 오른쪽 귀에서 시작해 뇌로 타고들어가는 바람에 전정기관을 비롯해 오른쪽 얼굴에 안면마비 증세가 나타났다. 이때 너무 상태가 안좋아 Lv1 코치였던 구구에게 우테코를 그만두겠다고 말했다. 다행히도 우테코 측에서 증세가 호전될 때까지 푹 쉬고 교육 과정에 다시 합류해도 좋다는 답변을 받았다. 그래서 우테코를 시작하고 첫 열흘 동..
프로그램과 프로세스, 스레드의 차이
서론 면접 질문으로 프로그램과 프로세스, 스레드의 차이에 대해 설명해달라는 질문을 받았다. 이에 대해 온전히 답변하지 못했기에 다시 공부하는 마음가짐으로 이 글을 적는다. Q. 프로그램과 프로세스의 차이에 대해 말씀해주세요. A. 프로세스는 실행 중인 프로그램을 말합니다. 하드디스크에 저장되어 있는 프로그램이 실행되면 메모리에 적재되어 CPU의 자원을 할당받아 프로세스가 됩니다. 프로그램은 수동적인 존재, 프로세스는 프로그램을 실행하는 능동적인 존재로 비유할 수 있습니다. 프로세스가 실행되면 PCB(Process Control Block, 프로세스 제어 블록)가 생성됩니다. PCB는 운영체제가 프로세스를 제어하기 위한 정보들의 저장소입니다. PCB에는 실행될 다음 명령어 주소를 저장하는 프로그램 카운터를..
JPA 성능 개선기 4. saveAll()
상황 현재 스케줄을 등록할 때 기존 스케줄을 deleteAll한 뒤, 새로운 스케줄을 saveAll하는 방식을 취하고 있다. 기존에는 하루씩 일정을 등록할 수 있었으나, 사용자의 피드백을 반영하는 과정에서 다중선택 기능이 추가되었다. 따라서 여러 날의 일정을 한번에 등록할 수 있게 되었다. 문제점 여러 스케줄을 등록할 때 스케줄 하나하나마다 save 쿼리가 나가 DB에 부하를 주고 있는 상황이다. 코드 private void saveAllByCoachAndDate(Long coachId, ScheduleUpdateRequest request) { Coach coach = findCoach(coachId); List schedules = toSchedules(request, coach); scheduleR..
JPA 성능 개선기 3. 페치조인
상황 코치가 크루 한명의 면담 히스토리를 조회할 때 crew_id, reservation_status 조건에 맞는 모든 면담을 조회한다. 문제점 조회한 면담을 DTO로 변환해 필요한 정보를 응답값으로 넘겨줄 때 SELECT 쿼리가 의도치않게 발생하는 문제가 발생했다. 하나의 면담마다 SELECT 쿼리가 2개씩 추가로 발생하는 N+2 문제가 발생한 것이다. 코드 Service public List findCrewHistoryByCoach(Long crewId) { validateCrewId(crewId); List reservations = reservationRepository.findAllByCrewIdAndReservationStatus(crewId, DONE); List response = new ..
JPA 성능 개선기 2. 1+N 문제 우아하게 해결하기
상황 기존에는 크루 메인뷰에서 단순히 코치 목록을 조회했으나, 사용자 피드백을 받는 과정에서 코치가 면담가능한 일정이 등록되어 있는지 메인뷰에서 알고 싶다는 피드백이 들어왔다. 코치를 매번 클릭해서 등록된 일정이 있는지 찾는 과정이 번거로웠던 것 같다. 그래서 아래와 같이 예약가능한 코치일 경우 오른쪽 상단에 초록점을 통해 표시하도록 만들기로 했다. 문제점 코치가 한명일 때는 문제가 없었지만, 코치 수가 늘어남에 따라 coach_id에 해당하는 schedule 테이블을 조회하는 쿼리가 비례해서 나가는 상황이 발생했다. 즉, 코치수에 비례해 쿼리가 하나씩 추가로 발생하는 1+N 문제가 발생한 것이다. 코드 @Transactional(readOnly = true) public List findAll() { ..
JPQL을 사용할 때는 join 타입을 꼭 명시하자
상황 Spring Data JPA 사용시 @Query 애노테이션으로 JPQL을 사용하면서 문득 이상한 점을 발견했다. 어떤 쿼리가 나가는지 확인했을 때 내부적으로 cross join을 사용한 것이다! 평소에 inner join이나 left join 정도만 알고 있었던 터라, cross join이 무엇인지 잘 몰랐다. cross join이 무엇인지 알아보고, 이것을 어떻게 해결할 수 있는지 알아보자. 테이블 결합 방식 교차결합(Cross Join) 교차결합(Cross Join)은 카티전곱(Cartesian product)라고도 불리며 곱집합으로 계산된다. 곱집합은 미드 시리즈와 비슷하다. 시즌1부터 6까지 각 10편씩 있다고 가정하면, 시즌1-1, 시즌1-2, … 시즌 6-10 까지 총 60편(6x10)이..