All
34 posts
서버리스와 람다로 더 싸고 유연하게 구조 개편하기

최근 디어에 알림함이 생겼다. 근데 최근이라고 쓰고 확인해보니 최초 오픈한지 이미 딱 한달이 지났다… 요즘 시간 지나가는 속도가 정말 충격적이다… 어쨌든 그 전에 디어엔 ‘알림’ 개념이 없었다. 몇 기능에 푸시 알림이 붙어 있었을 뿐이다. 공유 모빌리티 서비스를 사용한 적이 있다면 앱 체류 시간을 떠올려 보자. 굉장히 짧지 않았나? 나도 길에서 킥보드가 보이면 대여할 때 한 번, 반납할 때 한 번 앱을 키는 게 전부다. 그래서 알림의 필요성이 부족해 없었다. 그러다 게이미피케이션 같이 고객과 상호작용이 강한 기능이 도입되면서, 고객에게 전달한 정보가 어디에도 남지 않고 휘발된다는 문제점을 팀 디자이너 분이 발견했다. 알림함은 그 분의 오랜 숙원 사업이었는데, 오픈하고 보니 ‘필요없다’고 생각해서 고객에게 전하지 않던 정보 중 필요한 것도 있었고, 원래 도입하려던 기능에 알림이 큰 도움이 되는 것도 있었다. 🔔 알림 도입과 아키텍쳐 개편 인앱 알림 도입 이전엔 푸시 알림만 여러곳에서…

February 18, 2024
etc
2023년 회고 겸 1년차 회고

2023년도 회고를 이제와서 올린다니? 싶겠지만 이유가 있다. 작년 말에 우리 팀은 12월 23일 ~ 1월 1일까지 끝내주는 휴가를 다녀왔다. 그래서 휴가 기간동안 뭘 했냐면… 밥먹고 잠자고 화장실 갈 때만 빼고 (그리고 그와중에 어떻게 인프런 강의를 하나 들었다) 발더스 게이트3 게임을 했다. 그러려던 건 아닌데, 재밌다는 얘기를 하도 들어서 ‘그럼 딱 휴가 때 하고 남은 시간에 할 거 해야지~’ 했으나 이렇게 볼륨이 큰 줄 몰랐다. 해도 해도 안끝나서 거짓말처럼 1월 1일 밤 12시에 엔딩 크레딧을 봤다. 개발 블로그가 자기 홍보의 수단 중 하나란 걸 생각하면 회고 처음부터 미친듯이 게임했다는 얘기를 쓰는게 해로울 것 같은데, 이 얘기를하는 이유가 있다. 올해 내내 회고글 써야지 생각만 계속 했다. 3개월 수습 끝나면 써야지, 엇 늦었으니 6개월 반년 회고 해야지… 하다가 정신차리니 12월이었다. 그럼 휴가 때 써야지ㅎㅎ 했다가 해가 지나고, 이제 3일 있으면 입사 1년차가…

January 07, 2024
회고
자바스크립트에 불시착

많은 스타트업에서 백엔드 언어로 자바스크립트를 쓰고 있다. 나는 자바스크립트랑 node.js로 바닥부터 개발을 해보지 않아서 모르지만, 다른 언어와 프레임워크에 비해 프로덕트를 빠르게 낼 수 있어, 초기 스타트업에서 많이 사용한다고 들었다. 그런데 나처럼 특정 언어와 프레임워크를 사용하는 백엔드 교육 과정으로 개발을 시작한 사람은 배운 것 밖에 쓸 줄 모른다. 대부분의 교육 과정에서 가르치는 자바•스프링이 공개된 자료도 훨씬 많다. 그런데 예전에 구직 사이트에서 신입 공고를 볼 때 자바스크립트•노드 스택이 많았다. 가고 싶은 회사 중 한 곳이었던 인프런도 자바스크립트•노드 스택이었다. 취준 때 스택에 상관없이 이곳저곳 서류를 넣고 면접을 보면서 <자바 스프링이 아닌 무언가>를 사용하는데 괜찮으세요 라는 질문을 받으면 언어랑 프레임워크는 도구일 뿐이죠!😉 라고 답하면서 허세는 잔뜩 부렸는데, 솔직히 나도 할 줄 아는 걸로 해먹고 살고 싶었다. 편하니까. 다행스럽게 자바•스프링을 사용…

December 10, 2023
회고
새는 시간을 줄이고 싶다는 고민

지난 반 년간 회사에서 한 ‘개발’을 돌아봤을 때, 절반은 Node.js의 레거시를 스프링으로 옮기고, 그에 수반되는 작업에 해당되고, 나머지 절반은 동시에 새로운 요구사항을 Node.js와 옮긴 신규 시스템에 붙이는 일에 해당되는 것 같다. ‘달리는 기차의 바퀴를 갈아 끼우’면서 동시에 열차 칸을 열심히 붙이고 있다. 나는 레거시라는 단어의 절묘함을 좋아한다. 레거시가 있어서 회사가 먹고 살았고, 나도 들어올 수 있었다는 점에서 ‘유산’이라는 의미가 딱 맞다. 그리고 동시에 언제까지나 유산에 의지해서 살 수 없다는 면도 그렇다. 그래서 레거시를 부정적인 뜻으로만 사용하는 걸 보면 조금 슬퍼진다. 어쨌든 레거시 코드를 보며 회사 도메인 정책을 파악하는 일이, 좋은 사내 문서와 더 좋은 살아있는 레퍼런스인 팀원들이 있음에도 만만치 않았다. 예외 상황은 너무 많았고 코드가 복잡해 쉽게 파악할 수 없었으며, 아무도 그렇게 돌아가고 있는 줄 모르던 부분을 발견하기도 했다. 그러다 팀에서…

July 02, 2023
etc
회고
배포 중 순단을 없애고 싶었을 뿐인데

⚡️ 문제 상황 언젠가부터 백엔드 서버 배포 직후에 아주 짧은 서비스 순단이 일어났다. 배포 직후 외부 API를 호출 할 때 DNS 조회에 실패하는 걸로 추정되었다. 여러번 발생하는 에러가 아니기에 다른 팀원이 애플리케이션 실행 후 트래픽 허용 전, 으로 호출하는 모든 도메인을 한 번씩 조회하도록 배포 스크립트를 수정했다. DNS 조회 결과를 캐싱할 것으로 기대했기 때문이다. 하지만 조치 후에도 여전히 이라는 동일한 에러 메시지와 함께 순단이 발생했다. 순단으로 인해 틀어진 여러 정합을 수동으로 맞춰야 하는 상황을 없애기 위해 이번 스프린트에 해결을 목표했다. 🧶 EAI_AGAIN은 어디에서 오는가 이 코드를 누가 언제 왜 던지는가 부터 알기 위해 라이브러리를 포함해 코드를 검색했는데 나오지 않았다. 그래서 함수 이름으로 추정되는 를 검색해보고, 에러 콜스택도 읽어봤다. 프로젝트 및 노드 모듈 코드 내에 라는 함수는 없었고, 대신 노드 모듈 내의 파일의 주석에 언급이 있었다. …

June 04, 2023
etc
CS
[JPA] @Transactional이 없다고 레포지토리가 왜 터져?

🧶 문제상황 서버 오픈 전 부하테스트로 대비하기의 경험으로, 요즘 코드를 짤 때 외부 호출이 끼어있다면 트랜잭션을 최소로 잡고 있다. 거기다 더티 체킹도 사용하지 않고 명시적으로 다시 저장해주는 방식을 사용 중이다. 이건 교휸이 있어서는 아니고, 그냥 성향이다. 더 읽기 명확한 것 같고? 여기에 아이템을 삭제하는 기능을 추가 개발하게 되었다. 그리고 테스트를 실행하니, 아래와 같은 에러 메시지를 던지며 터졌다. No EntityManager with actual transaction available for current thread - cannot reliably process ‘remove’ call; nested exception is javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably…

May 07, 2023
JPA
트러블슈팅
이상한 부업 일기 - 나는 얼마나 고객을 알고 있을까

어느날 문득 천재적인 생각이 떠올랐다. ‘벚꽃철에 석촌호수에서 폴라로이드 사진을 돈 받고 찍으면 부자가 될 수 있지 않을까?’ 우리 회사엔 는 그라운드 룰이 있다. 예시로 ‘비오는 날에 킥보드 이용이 줄어든다’는 팩트, ‘킥보드에 우산을 달면 이용률이 올라갈 것이다’는 가설이다. 이 룰에 따라 내 발상을 표현하자면 다음과 같다. 팩트 인생네컷과 같은 사진 촬영, 즉석 출력 서비스가 인기가 많다. 인생네컷에는 지역, 계절별로 특별한 프레임, 예를 들어 벚꽃 프레임 같은 것이 한정판으로 존재한다. 가설 요즘 사람들은 디지털 사진을 찍는 것이 대부분이다. 그래서 실물 사진을 갖고 싶어 한다. 사실 인생네컷 같은 실물 사진을 벚꽃과 함께 찍고싶지만, 그러기 힘들어서 벚꽃 프레임 같은 걸로 대리만족 하고있다. 이 아이디어를 회사 사람들에게 얘기했을 때, 소수의 몇명은 돈이 되겠다 동의하고 몇명은 반대했다. 제일 긍정적인 의견이 한 10만원 벌 것 같다 였고, 제일 비관적인 의견은 만원이나…

April 09, 2023
etc
[JPA] 실종된 데이터와 연관 객체 조회하기

백엔드 면접 단골 질문 중 하나가 이다. 물론 몇 달 전까지 나도 줄줄 외우고 있었다. dto로 갖고 오던가, 페치 조인이 엔티티 그래프가 어쩌고 배치 사이즈를… 그리고 몇 개는 실제로 적용해서 문제를 해결해보기도 했지만, 비교적 전형적인 케이스만 다뤘기에 적용했더니 해결됐다, 끝! 이었다. 그래서 최근에 을 해결하기 위해 페치 조인을 쓰다가 동작을 잘 모른다는 걸 알게 되었다. 🎁 문제 상황 단방향 연관관계를 가진 두 엔티티가 있다. 는 유저가 획득한 아이템이다. 는 아이템을 획득, 또는 사용될 때 생기는 로그다. 엔티티 , 는 다음과 같은 비즈니스 로직을 가진다. 아이템 로그는 아이템에 취한 행동에 따라 , 이 정해진다. 아이템 획득은 -> 순서로 이뤄진다. 이 후 까지 로직에서 문제가 생기더라도, 은 남아야 한다. 따라서 는 아이템 로그를 가지지 않을 수도 있다. 두 엔티티는 단방향 간접참조로 연결되어있다. 아이템 로그는 아이템 획득 엔티티를 모른다. DB에는 두 테이블…

March 26, 2023
트러블슈팅
JPA
서버 오픈 전 부하테스트로 대비하기

💡 해당 글은 사내에 작성한 문서를 허가 하에 개인 포스팅용으로 적절히 수정한 글입니다. 디어에 입사하고 처음 맡은 일은 개발 중이던 신규 인터널 API 서버 개발을 마무리하고 프로덕션 환경에 올리는 것이었다. 전체 사이클에서 내 생각에 한 80% 지점에 참여하게 되었다. 현재 신규 서버는 프로덕션 환경에 올라간 채로 ‘회사 사람들이 디어 앱을 통해 하는 요청’ 이라는 티끌의 트래픽만 받고 있는데, 다음 2주 간의 스프린트에 전체 트래픽을 100% 전환하는 게 목표다. 그래서 이번 스프린트 중에 이 서버의 성능을 테스트하고, 운영 환경에 적절한 인프라 설정값을 찾는 과제를 수행했다. 🏗 인프라 구조 모든 인프라 구조도는 극히 단순화하여 그렸다. 기존 프로덕션 인프라 구조 신규 인터널 서버는 기존 디어 서버에서 외부 API 연동이 잦은 특정 도메인을 분리한 서버다. 기존에는 디어 앱에서 특정 요청이 들어오면, 디어 서버를 거쳐, 경우에 따라 또 다른 인터널 서버를 경유해 로직을 수행…

March 12, 2023
트러블슈팅
열 번 들어 안 기억하는 나를 위한 친절한 오브젝트

이 책은 객체지향의 바이블일 것이다. 책을 읽기 전부터 그런 생각을 했다. 추상적인 표지와 무지막지한 두께에서 느껴지는 포스가 흡사 수학의 정석 같았기 때문이다. 그래서 그렇게 어려운 책이 아니라는 주변의 말에도 쉽게 읽을 엄두를 못 냈다. 그러다 회사에서 페어 프로그래밍을 할 때였다. 클라이언트 입장에서 요청으로 엔티티 값을 변경 시키고, 다시 요청으로 엔티티를 조회하도록 코드를 짜고 있었다. 그래서 서비스의 엔티티 값을 변경 시키는 메서드가 해당 엔티티를 반환하게 만들면, 굳이 요청을 다시 보낼 필요가 없지 않겠냐는 주장을 했다. 그 때 팀원이 이야기를 하면서 오브젝트 책을 추천했다. 설날 전부터 읽기 시작했으니 다 읽기까지 약 한달이 걸렸다. 책이 어려워서는 아니고 회사를 다니니 시간내서 공부하기가 쉽지 않았다. 블로그 포스팅 해야한다고 글또를 신청해놓고 지각하고 있는 지금을 봐도 그렇다… 어쨌든, 책에서 인상깊었던 부분을 간략하게 정리해봤다. 💎 처음 만난 지식들 명…

February 27, 2023
독서
우아한테크코스를 떠나며

유난히 길고 힘들었던 2022년이 지났다. 와 이라는 두가지로 축약되는 해였다. 글을 쓰기 시작한 건 작년 30일인데, 이제야 올리려니 머쓱하지만😓 그래도 회고 완성했다! 🔥 취업 회고 감사하게도 와 , 그리고 다른 두 곳에 최종 합격했다. 카카오페이 합격 통보 시점에 나머지 진행 중이었던 곳들은 중단한다는 연락을 드렸다. 모두 진지하게 고려중인 회사였으나, 현실적으로 두 회사의 입사일 전에 결과가 나오기 어려운 상황이었다. 22년도 안에, 그러니까 해가 바뀌기 전에 취업하기가 목표였는데 기대보다 좋은 결과로 무사히 달성했다. 같은 어그로 업적을 달성한 스스로가 자랑스럽기도 하고(ㅋㅋ) 취업연계를 제외한 곳에서도 예상 외의 좋은 기회를 많이 받았기에 어떤 점이 좋았고 아쉬웠는지 정리해봤다. 💯 이건 정말 잘했다 블로그를 썼다!!! 우테코 기간 동안 블로그를 성실히 쓴 다른 크루들에 비하면 글 수는 적다. 면접 보던 시점에 포스팅이 20개 정도 있었으니, 2주에 하나쯤 쓴 셈이…

January 06, 2023
회고
우아한테크코스
Querydsl만의 아늑한 🏡 지어주기

🧶 문제상황 🪐 비대해진 서비스 코드 줍줍은 요청에 따라 동적으로 변화해야 하는 복잡한 조회 조건을 걸기 위해 을 도입했다. 예전에 공부하며 가볍게 사용해 본 적은 있지만, 줍줍 요구사항만큼 복잡한 코드를 짜 본 적은 없었다. 에 코드를 넣는 식으로 우선 구현했고, 무사히 배포되었다. 그러다 을 쓰지 않는 다른 서비스 클래스 코드를 보니 ‘어… 여기는 너무 깔끔한데?‘하는 위화감이 들었다. 그리고 다시 을 쓰는 코드를 보니, 가 할 일이 에서 이뤄지고 있다는 생각이 들었다. 위에 있는 기존 의 짧은 예시 코드 내에서도 사용으로 인한 서비스 역할 비대화가 보인다. 의 경우 DB에서 데이터를 가져오는 역할을 완벽히 에 맡기고 있다. 반면, 는 DB에서 어떤 데이터를 가져올지 서비스 코드 상에 완전히 노출되어 있음을 볼 수 있다. 그래서 각 레이어 별 역할이 원칙대로 분리되도록 코드를 별도의 객체로 빼내는 리팩토링을 시작했다. ✂️ 일단 레포지토리 코드 분리 사용 예시를 보면 을…

October 26, 2022
Spring
트러블슈팅
etc
[JPA] EnableJpaAuditing의 내부와 CI의 소중함

💣 문제상황 줍줍에는 북마크 설정한 메시지를 모아서 보는 기능이 있다. 기존에는 이 북마크 목록을 보여줄 때, 북마크가 등록 된 메시지의 생성 시간 순서대로 보여줬다. 그러다 사용자 편의를 위해 이를 북마크 등록 시간 순서대로 보여주기로 바꿨다. 이 때, 북마크 등록 시간을 편하게 관리하기 위해 을 도입했다. 그리고 해당 PR은 순조롭게 머지 되었는데… 팀원 봄이 진행한 컨트롤러 테스트를 WebMvcTest로 개선하는 PR에서 문제가 생겼다. 봄의 로컬에서 테스트가 잘 돌아가는 상태였는데, PR의 github action에서는 테스트가 실패했다. 로 변경한 모든 용 컨트롤러 테스트가 같은 이유로 실패하고 있었다. 라는 문구가 눈에 띈다. 해당 문구로 라이브러리를 검색해보면 라는 클래스가 나온다. 사실 이 문구로 검색하면 많은 사람들이 해결법을 이미 올려두었다. 그런데 여기까지 오니, 이 대체 뭔데? 도 아니고 라고? 이거랑 은 무슨 상관이지? 등등 궁금한 점이 생겨서 코드를 조금…

October 14, 2022
Spring
JPA
트러블슈팅
줍줍 MySQL 인덱스 탐험

🧳 줍줍 MySQL 인덱스 탐험 ❗️ 해당 포스팅에서 지칭하는 책은 모두 Real MySQL 8.0 1권을 뜻합니다. 우테코 팀 프로젝트 5차 스프린트에서 성능 테스트로 톰캣 설정 최적화 / 모든 쿼리 수집 후 DB 인덱스 설정 이라는 두 개의 백엔드 과제가 있었다. 나는 이 중 DB 인덱스 설정을 맡게 되었다. 줍줍의 전체 테이블 구조는 정석 ERD보다 간략하게 표현하자면 이렇다. 쿼리 수집은 쉬웠다. 줍줍의 모든 클래스들은 를 상속했다. 는 선언하지 않은 메서드도 사용 가능한 반면, 를 상속하면 선언한 메서드만 사용 가능하다. 뒤집어 말하면 사용을 제외하면, 코드의 모든 메서드가 곧 프로젝트에 사용 중인 모든 쿼리였다. 쿼리 최적화 by.봄🌱 인덱스 최적화를 시작하기 전에 고맙게도 같은 팀 크루인 봄이 불필요햔 left outer join을 제거하는 쿼리 최적화를 해주었다! 에서 의 PK를 FK로 가진 가 해당 FK를 조건으로 조회할 때, 로 하면 불필요한 이 발생하고 …

October 04, 2022
etc
우아한테크코스
트러블슈팅
메시지 조회 테스트 개선기

🛠 메시지 조회 테스트 개선기 초난감 메시지 조회 줍줍은 슬랙 메시지를 날짜이동, 윗방향 스크롤, 아래방향 스크롤, 단어검색, 특정 채널만 보기 등 여러 조건으로 조회할 수 있다. 사용자 편의를 위해 이렇게 다양한 조회 조건을 지원하다 보니 동적 쿼리 생성이 필요해 도 도입했다. 작성된 조회 코드와 테스트 작성을 위해 파악된 케이스만 봐도 복잡도가 짐작 갈 것이다. 어떤 점을 개선하고 싶었나 해당 메시지 조회 기능 개발은 다른 팀원들이 맡았다. 그래서 올라온 PR을 봤는데, 동작은 잘 했으나 코드 개발에 참여하지 않은 입장에서 테스트가 알아보기 어려웠다. 처음 테스트를 읽었을 때 왜 읽기 어렵다고 느껴졌을까? 먼저 데이터가 문으로 들어가는 게 원인 중 하나였다. 메시지 조회를 하려면 미리 저장된 1.멤버(사용자) 2.채널 3.채널 구독 데이터가 필수로 필요했다. 기본적으로 메시지에 의존관계가 있고, 조회 시 구독하는 채널 메시지만 필터링 하는 분기가 기본으로 있었기 때문이다.…

September 28, 2022
Spring
트러블슈팅
✨🌈💫테스트💫🌈✨ (토비의 스프링)

해당 포스팅은 토비의 스프링 3.1을 읽고 책 내용과 실습 코드 정리 및 스터디에서 나온 의견을 정리한 포스팅이다. 2장 테스트 스프링을 국비학원에서 처음 배운 나는 가 존재하는 줄도 몰랐다. 자잘한 코드 하나 고치는 데도 대소동이 일어났다. 회원가입 기능을 만드는데 비밀번호 제한이 잘 안되는 것 같다면 애플리케이션을 종료한다 코드를 수정하고 break point를 걸거나 출력문을 써둔다 다시 애플리케이션을 킨다 크롬 시크릿 + 강력 새로고침으로 페이지에 들어간다 회원가입을 시도하고 다시 확인한다 이런 과정을 거쳐야 했다. 테스트가 일상이 된 지금은 테스트가 없으면 불안하다. (레벨4 미션을 하면서 소홀해지긴 했지만…) 테스트를 배운 처음엔 신기했고, 그 다음엔 조금 귀찮았는데, 지금은 테스트가 없으면 줄 없이 번지점프하는 기분이 든다. 테스트는 나에게 자유롭고 재밌게 코드를 갖고 놀게 해주는 안전장치인 셈이다. 초난감 UserDaoTest 개선기 1장에서 만들었던 는 내가 예전…

September 18, 2022
Spring
오브젝트와 의존관계 (토비의 스프링)

해당 포스팅은 토비의 스프링 3.1을 읽고 책 내용과 실습 코드 정리 및 스터디에서 나온 의견을 정리한 포스팅이다. 1장 오브젝트와 의존관계 늘 만 생각했기에, 1장 서두의 가 중점인 스프링의 핵심 철학이 인상깊었다. 그래서 포스팅을 인용으로 시작한다. 자바 엔터프라이즈 기술의 혼란 속에서 잃어버렸던 객체지향 기술의 진정한 가치를 회복시키고, 그로부터 객체지향 프로그래밍이 제공하는 폭넓은 혜택을 누릴 수 있도록 기본으로 돌아가자는 것이 바로 스프링의 핵심 철학이다. 그래서 스프링이 가장 관심을 많이 두는 대상은 오브젝트다. p.53 초난감 DAO 개선기 JDBC API를 처음 배우며 만들었던 모습의 클래스를 만들었다. 제일 기본적인 기능으로 User 정보를 단건 저장하는 , 단건 조회하는 이 있다. 비록 동작은 잘 하지만 썩 잘 짠 코드 같진 않다. 어느 부분이 문제일까? 책에서는 세 가지 관심사가 섞여있는 것이 문제라고 한다. DB 연결 커넥션 가져오기 SQL 문장을 담은 St…

September 11, 2022
Spring
[Spring] 모든 요구사항을 한 엔드포인트로 처리해보자! 😂

해당 포스팅은 줍줍 개발 과정 중 맞딱뜨린 문제점과 답을 찾아가는 과정을 다른 방식으로 재구성한 글이다. 생각보다 글이 길어진 고로, 문제상황과 해결방안만 보고싶다면 문제상황 빈 컬렉션 주입을 이용한 해결 예시코드 이 둘을 보기를 권한다. 간단한 게시판 서비스를 상상하기 회원 가입과 탈퇴 당신은 지나가던 고양이의 의뢰로 서버를 개발하게 되었다. 고양이는 🐱 닉네임을 입력하면 가입이 가능하고, 탈퇴할 수 있는 서비스를 만들어 주세요 💬 라고 요구했다. 그래서 나는 (그리고 이 글을 볼 대부분의 사람들은) 이건 쉽지~ 하고 간단한 컨트롤러를 만들었다. 그런데 이제 엔드포인트를 하나로 하고 이 코드를 본 고양이가 말했다. 🐱 엔드포인트를 하나로 통일할래요. 그리고 이게 회원 가입인지 탈퇴인지는 body안에 쓸게요. 이렇게요. 💬 코드가 이상해지기 시작한다. 그래도 아직 납득 가능한 수준이다. 여기에 포스팅 기능도 몽땅 넣어줘 이 코드를 본 고양이가 또 요구했다. 🐱 각자 게시글을 쓰고,…

August 27, 2022
Spring
트러블슈팅
[JPA]는 새로운 엔티티를 어떻게 알아볼까?

Long id = 0L ? 코틀린을 공부하다 참고하려고 우테코 지원 플랫폼의 코드를 봤다. 그 중 흥미로운 점을 발견했는데, 엔티티를 생성할 때 를 로 초기화 하는 것이다. 이게 왜 흥미로웠냐면 상수 픽스쳐 사용 주의 포스팅에서 썼듯이 가 이 아니면 를 시행한다고 생각했기 때문이다. 굳이 로 초기화하면 비용만 추가로 들 것 같았다. 그래서 자바 스프링에서 직접 간단한 엔티티를 만들고, id를 로 지정해 저장해봤다. 실행된 SQL문을 보면, 역시나 문이 문에 선행되었다. 대신 가 수행된 것이다. JPA의 새로운 엔티티 식별법 상속 시 쓰게 되는 구현체인 의 를 다시 살펴보자. 참 명료한 언어로 잘 짜여있다. 니까 엔티티가 새로운 엔티티라면 를, 아니라면 를 수행한다. 그렇다면 이 는 어디서 가져오는 걸까? 를 구현한 몇 개의 클래스에 디버깅을 걸며 찾아보니 라는 낯선 이름의 클래스에 걸렸다. 코드 상 를 판단하는 조건은 다음과 같다. 엔티티의 가 원시 타입이 아니라면 일 때 …

August 24, 2022
JPA
kotlin
[Spring] @PostConstruct를 막아라

문제상황 서비스 배경지식 첫번째 참고 현재 개발중인 줍줍은 슬랙 무료 워크스페이스의 사라지는 메세지들을 대신 저장하고 보여주는 서비스다. 메세지 저장을 위해 최초 어플리케이션 구동 시, 해당 워크스페이스에 속한 모든 회원 정보를 가져온다. 이 역할을 라는 클래스의 안에 작성했다. 이유는 아래와 같았다. 어플리케이션이 구동하는 동안 발생하는 신규 가입, 탈퇴 이벤트는 실시간 반영이 된다 하지만 어플리케이션 최초 구동 전, 또는 업데이트 배포로 어플리케이션이 중지된 사이에 발생한 이벤트는 반영이 안된다 따라서 재구동 시 한 번 슬랙 API를 호출하여, 유저 정보를 업데이트한다 유저 정보를 메시지에서 참조하고 있어서 저장이 선행되어야 했다. 또, 로그인 시 이 정보와 슬랙 로그인으로 받은 정보를 대조해서 자체 토큰을 발급하는 까닭도 있다. 두번째 참고 슬랙은 라는 이름으로 슬랙 API에 HTTP 요청을 보내고 응답을 받는 객체를 제공한다. 그래서 슬랙 API 호출이 필요한 곳에서…

August 23, 2022
Spring
트러블슈팅
[JPA] 상수 픽스쳐 사용 주의

문제상황 우테코 QNA 미션에서 상수로 선언된 엔티티 픽스쳐가 있었다. 레벨3 같은 팀 크루인 봄이 해당 미션을 진행하다 테스트가 터져 어쩌다보니 같이 원인을 찾게 되었다. 상황을 비슷하게 복구해보자면 이런 구성이었다. 원본 미션 코드에서는 픽스쳐가 로 별도 클래스에 선언되어 있었다. 그런데 테스트 클래스 하나에서만 사용되고 있어서 해당 클래스로 옮겼던 것 같다. 나도 픽스쳐를 옮겼다가, 평소 쓰는 방식대로 한다고 지웠었다. 어쨌든 와 는 의 단방향 연관관계였고, 는 를 통해 저장해주는 상태였다. 그러다 테스트가 터지며 의문의 에러메시지를 마주했다. org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [FK83S99F4KX8OIQM3RO0SASMPWW]; nested exception is org.hibernate.exception.Con…

August 13, 2022
JPA
트러블슈팅
야생에서 사과씨 심기 (@Bean)

야생 학습을 하면 자연스레 지식이 실전을 뒤따르게 된다. 우테코에서 처음 제대로 경험한 야생 학습은 낯설었으나 너무 잘 적응한 탓인지 어느 순간 당장 쓰이지 않을 지식을 공부하는 게 마땅찮았다. 당장 터지는 테스트를 고치고 싶을 뿐인데 왜 을 알아야 하지? 이걸 쓸 때가 있을까? 좋게 말하면 야생, 나쁘게 말하면 땜빵 마인드로, 그래도 연계되는 지식을 우겨넣고는 있었다. 언젠가는 쓸모가 있겠지 하고. 이런 알지만 알지 못하는 죽은 지식이 레벨3 프로젝트를 하다 죽은 줄 알았지만 다 때가 있구나! 로 바뀌는 순간을 겪었다. @Bean은 외부 라이브러리를 등록하고… 나에겐 이 알지만 알지 못하는 죽은 지식이었다. @Bean과 @Component의 차이 포스팅을 쓰기도 했고, 의 쓰임새가 뭐냐고 하면 줄줄 얘기할 수 있었다. 개발자가 직접 제어할 수 없는 외부 라이브러리 클래스를 빈에 등록할 때 사용됩니다. 하고. 그런데 좀처럼 을 사용할 일이 없었다. 그러다 레벨3 프로젝트인 줍줍…

August 02, 2022
Spring
회고
우아한테크코스
[git] 슬랙한테 봇 강퇴당하고 서브모듈 도입한 이야기

슬랙이 봇을 강퇴시켰어요 서버에서 슬랙 API를 호출하려면 발급받은 봇 토큰이 필요하다. 해당 정보를 기밀이라고 생각하지 않았는데… 애초에 봇에게 호출할 수 있는 API 제한이 있다 연결된 워크스페이스가 개발을 위해 생성된 줍줍 팀 워크스페이스다 라는 이유에서였다. 그래서 깃헙에 을 포함한 을 올려놨는데… 어느날 API 응답이 오지 않았다. 개발자 도구의 응답에는 이라는 에러 문구가 떴고, 분명 워크스페이스에 정상 추가했던 봇이 사라져 있었다. 슬랙이 봇을 강제 추방시킨 것이었다… 얼마간 잘 썼기에, 일정 주기로 공개 저장소들을 크롤링 해 한번에 정지시키는 게 아닐까 싶다. 설명서를 잘 읽자 슬랙 API에 들어가면 가 떡하니 명시되어 있다. 봇 토큰에는 큰 권한이 있습니다. 토큰은 사용자가 앱을 설치함으로써 권한을 부여했음을 나타냅니다. 앱을 설치한 유저가 준 신뢰를 해치지 않도록 토큰을 안전하게, 기밀로 보관하세요. 최소한 공개적인 형상관리에 토큰을 올리지 마세요. 환경 변…

July 25, 2022
etc
트러블슈팅
세션의 정체를 찾아서(with 🍪, 🪙)

🔍 세션의 정체를 찾아서 세션의 정의 영어에서 이란 특정 활동이 수행된 기간을 의미한다. 일상 속에서 보자면 나는 꾸준히 PT를 받고 있는데, PT 수업 한 회를 세션이라고 불렀다. 그럼 CS의 세션은 무엇일까? ****을 의미한다. 통신을 하는 동안 세션이 유지된다면 세션의 정보를 이용할 수 있을 것이다. 이런 상태를 이라 부른다. 반대는 라고 부르는데, HTTP 프로토콜이 이에 속한다. (막간 홍보 : HTTP에 관심이 있다면 HTTP 테코톡) HTTP 프로토콜이 이기에, 여러 불편한 상황이 일어난다. 쇼핑몰에서 상품을 장바구니에 담을 때 마다 로그인을 새로 요구한다고 생각해보자. 짜증나서 사려던 것도 안 사고 나가지 않을까? 이런 무상태를 보충하기 위해 상태 유지를 돕는 기술을 함께 사용한다. 그 중 하나가 이다. javax servelet HttpSession 자바 서블릿의 은 인터페이스다. 이 포스팅에서 다룰 내용을 java docs에서 간추려보았다. 유저 정보를 저장함으…

July 09, 2022
Spring
CS
[Spring] @JdbcTest, @WebMvcTest, @SpringBootTest

DB를 연동하고 스프링을 쓰기 시작하면서 어플리케이션의 구조가 복잡해졌다. 그에 따라 테스트도 다양한 어노테이션을 활용하여 작성해야 했는데, 처음에는 예제를 보며 따라했다. 그러다 각 어노테이션의 정확한 역할과 적용되는 방식이 궁금해 미션을 진행하며 사용한 세 테스트용 어노테이션을 학습했다. @JdbcTest JDBC 기반 컴포넌트만 테스트하는 JDBC 테스트를 위한 어노테이션이다. 이 어노테이션을 사용하면 auto-configuration이 비활성화 되고, JDBC 테스트와 관련된 configuration만 적용된다. 기본적으로 가 붙은 테스트는 트랜젝션 처리가 되고, 각 테스트가 죵로된 후 롤백을 시행한다. 또한 명시됐거나 자동 설정된 DataSource 대신 인메모리 DB를 사용하게 된다.를 사용하면 이런 설정을 덮어쓸 수 있다. 전체 어플리케이션 설정을 사용하면서 인메모리 DB를 사용하고 싶다면, 이 어노테이션 대신 와 를 조합해 사용하는 게 낫다. 를 사용한다면 를 함…

May 29, 2022
Spring
[SQL] SELECT * 쓰지 말자

지금까지 DB를 사용하는 미션에서 컬럼 수가 적기에 문을 자주 썼다. 그런데 로 모든 컬럼을 가져오는 것 보다 컬럼을 명시해 가져오는 게 낫다는 영문 포스팅을 제이슨이 공유해주셔서 읽었다. 7 Reasons Why Using SELECT * FROM TABLE in SQL Query Is a Bad Idea 다음은 해당 포스팅을 전체 번역한 것이다. SELECT * FROM TABLE 쿼리문을 쓰는 게 좋지 않은 7가지 이유 인터넷에서 쿼리문을 쓰는 게 나쁘니 피하라고 하는 많은 글을 봐왔다. 그 대신 정확한 컬럼을 나열해야 한다. 이는 내가 주니어 개발자에게 가르치기도 하는 좋은 제안이자 좋은 SQL 작성 습관 중 하나인데, 많은 사람들이 그 이유는 설명하지 않는다. 왜 쿼리문에서 을 쓰면 안되는지 이유를 설명하지 않고 SQL 개발자들을 설득하기란 어려운데, 대개 Oracle database에서 를 실행하는 것으로 SQL 학습을 시작하기 때문이다. 이 글에서 왜 쿼리문을 쓰…

May 25, 2022
etc
Optional과 메서드 네이밍 find vs get

우테코 레벨1 웹체스 미션에서 일급 컬렉션에서 특정 요소를 로 꺼내는 메서드를 작성했다. 그런데 해당 요소를 그냥 꺼내는 메서드가 따로 있었고, 이름이 겹치고 싶지 않아 생각하다 를 붙였다. 레벨2에서 DB를 본격적으로 사용하며 객체에서 데이터 조회를 할 때, 와 중 무엇을 쓸지 고민했다. 은 처럼 느껴져서 를 사용했는데, 의 패턴을 보니 을 쓰는 경우가 많았다. 그래서 둘의 차이를 찾아봤다. find vs get 스프링 Data의 인터페이스는 를 반환한다. 반면 같은 스프링 Data의 JPA repository에서는 T를 반환한다. 는 찾는 값이 없을 경우 을, 는 찾는 값이 없을 경우 한다는 차이가 있다. 여기서 볼 수 있듯이 일반적으로 반환 값이 없을 수 있는 경우 을, 항상 있어야 하는 경우 을 붙인다. 를 쓰면 api 사용자에게 이름을 통해 반환값이 없을 수 있음을 알려 줄 수 있는 것이다. 반면, 반환형이 같은 컬렉션이라면 값이 없어도 이 아닌 을 반환하면 된다. …

May 23, 2022
Java
7SQL 스터디 회고

우테코 레벨1 sql 수업에서 두 sql 문제를 풀어야 했다. 첫번째 문제를 시행착오 끝에 풀고, 두번째 문제는 풀지 못했는데, 척척 푸는 크루들이 많은 걸 보고 sql 공부의 필요성을 절실하게 느꼈다. 그래서 일주일 간 매일 문제를 3개씩 푸는 스터디를 개설했다. 7SQL 기간 : 1주일 성격 : 각자 문제풀기 인원 : 7명 목표 : 기초적인 SQL 문법 익히기 진행 방식 : 매일 한 사람씩 돌아가며 SQL 문제를 출제, 각자 풀고 출제자가 채점 7SQL 노션 모집글에 자세한 진행 방식이 적혀있으며. 7SQL 스프레드 시트에서 진행 기록인 출제한 문제와 각자의 답안, 정답 여부를 볼 수 있다. 스터디가 끝나고 간단한 회고를 가졌다. 좋았던 점 공통적으로 언급된 좋았던 점 SQL 문법에 익숙해진다는 목표를 달성했다 실력이 늘었다 개별적으로 업급된 좋았던 점 자율 참여였다 시간을 많이 들이지 않고도 학습할 수 있는 방식이었다 아쉬웠던 점 공통적으로 언급된 아쉬웠던 점 같은 테이블과 …

May 11, 2022
우아한테크코스
회고
DAO 와 Repository

웹 체스 미션을 진행하면서 을 이용해 DB에 접근하는 모든 클래스의 이름을 라 지었다가 아래와 같은 코멘트를 받았다. 코멘트를 받기 전까지 와 가 이름만 다른 같은 개념이라 생각했다. 그래서 이 둘의 차이에 대해 알아보았다. @Repository 문서 스프링 어노테이션 자바 문서에는 다음과 같이 적혀 있다. 적용 된 클래스가 Repository 임을 나타냅니다. 이는 도메인 주도 설계(에릭 에반스)에서 정의한 저장소를 캡슐화하고, 저장하고, 검색하여 객체의 컬렉션처럼 다루는 메커니즘을 뜻합니다. Data Access Object와 같은 전통적인 자바 EE 패턴을 사용하는 팀도 이 스테레오타입을 DAO 클래스에 적용할 수 있습니다. 다만 그 전에 Data Access Object와 DDD-style repositories의 차이를 이해하는 것이 좋습니다. 이 어노테이션은 다목적 스테레오타입이고 개별 팀은 자신들만의 축소된 의미에 맞춰 적절하게 사용하면 됩니다. 어노테이트된 …

May 07, 2022
etc
[SQL] left join vs (inner) join

left join / (inner) join 7SQL 스터디를 하다 자신만만하게 풀었는데 기대한 답이 나오지 않는 문제가 있었다. 주문을 한 번도 하지 않은 모든 고객을 찾아주세요. 스터디는 w3schools의 sql 실습 페이지를 이용했는데, 고객의 정보가 있는 테이블과 테이블이 있다. 주문이 없는 고객을 찾기 위해 테이블에 테이블을 한 다음, 에 이 있는 걸 확인하려 했다. 그런데 실행 결과를 보니 가 없는 고객은 아예 결과에 잡히지 않았다. 아직 sql 문법에 익숙하지 않아서 키워드를 차례로 앞에 붙여봤는데, 일 때만 가 인 경우도 포함되어 나왔다. 찾아보니 은 , 을 포함한 은 을 나타낸다 한다. 를 하면, A 테이블의 모든 행을 조회하면서 B에 없는 값은 로 처리된다. 나머지 은 해당 사이트에서 지원하지 않아 써보진 못했지만, 스터디 덕분에 차이를 확실히 알게 되었다. left join / (inner) join

April 30, 2022
etc
레벨1 레벨 인터뷰 회고

레벨로그란? 우아한테크코스에는 가 존재한다. 일종의 모의 면접으로 한 레벨 동안 배운 내용을 인터뷰를 통해 점검하는 것이다. 6명의 팀으로 진행했는데, 레벨 로그를 토대로 1명의 인터뷰어를 3명의 크루 인터뷰이와 코치가 인터뷰하고, 2명이 옵저버(관찰자)로 참여한다. 역할은 돌아가면서 바뀐다. 나는 크루 와 코치 과 함께 했다. 인터뷰어 회고 레벨1 레벨로그는 키워드 중심으로 간략하게 작성했다. 레벨1동안 많은 걸 배웠지만 직접 로그로 쓰기 전 까지는 정확히 몰랐다. 그런데 인터뷰를 위해 로그를 쓰면서부터 한 번 정리할 수 있었다. 감사하게도 이 내 인터뷰 기록을 남겨줘서 복기가 쉬웠다. 그리고 가 저녁에 피드백을 보내줬다😭 정말 너무 고마워서 눈물이 났다… 테스트 코드의 유지보수 비용을 줄일 수 있는 방법에 대하여 답변 준비해보기 경험해보지 못한 사례나 모르는 내용에 대한 질문을 받았을 때, 차분히 모름을 인정하되 현재 생각나는 추론과 이유를 제시하기 인터뷰어로부터 같은 질문…

April 26, 2022
우아한테크코스
회고
[Spring] DB 연결 없는 컨트롤러 테스트에서 시작한 스프링 공식 문서 공부

사건의 발단 우테코 레벨1 마지막 미션인 웹 체스 강의에서 테스트 더블을 이용해 DB 연결 없이 DAO 객체를 테스트 하는 걸 배웠다. 웹 체스에 스프링 프레임워크를 적용하고 컨트롤러를 짜는데, 컨트롤러도 DB 연결 없이 테스트 할 수 있지 않을까? 하는 생각이 들었다. 체스방의 정보(id, name)을 담은 테이블을 대신 할 와 를 주입받는 를 만든 것 까진 아주 좋았다. 문제는 컨트롤러를 짜며 생겼다. 당초 계획은 를 주입받은 를 테스트 환경에서만 컨트롤러에 주입하기였다. 하지만 스프링에서는 사용자가 직접 new로 객체를 생성하지 않고 로 등록된 클래스를 스캔해 빈(Bean)으로 생성한다. 그래서 테스트에서만 필요한 객체를 주입 할 수가 없었다. 일단 해결은 했으나… 페어 더즈와 방법을 고민하다 지나가던 제이슨이 도와줘서 문제를 해결할 수 있었다. 먼저 test 폴더 하위에 를 추가로 작성해 프로덕션과 다른 설정이 적용되게 한다. 공식 문서에 따르면, 해당 설정은 이미 존재하…

April 25, 2022
Spring
우아한테크코스
레벨1 스터디 운영 회고

나는 살면서 스터디를 해 본 적이 없다. 공부는 혼자 하거나 최소 친구와 하는 게 편하고 좋았다. 개발도 비전공으로 독학 후 국비학원을 다녔다. 다른 사람들과 개발 얘기를 한 적도 당연히 거의 없었다. 이런 성향을 고치고 싶어 이펙티브 자바 스터디를 열었고, 레벨1을 겪으며 을 깨우치고 독서회를 열게 되었다. 방학을 맞아 가벼운 회고를 써본다. 객체지향의 사실과 오해 독서회 기간 : 일회성(약 2시간) 성격 : 독서회 인원 발표 : 4명 참관 : 7명 목표 : 독서 인사이트 공유 진행 방식 : 제한없는 자유발표 + 짧은 회고 정확한 날짜는 기억나지 않지만, 블랙잭 미션이 끝난 주의 금요일 저녁이었던 것 같다. 슬랙으로 신청을 받았는데, 신청 인원이 생각보다 저조해서 의기소침해져 있었다. 모집글에는 단 한 명만 신청해도 둘이서 진행한다고 써놓긴 했지만… 그런데 뜻밖에도 참관객이 많이 와서 기뻤다. 발표 인원이 4명 뿐이라 별도의 시간 제한 없이 자유로운 발표로 진행했다. 객체지향…

April 19, 2022
회고
우아한테크코스
객체지향의 사실과 오해 (내 블랙잭은 왜 망했을까)

객체지향의 사실과 오해는 널리 알려진 개발자 필독서 중 하나로, 김영한님의 인프런 강의를 듣다 알게 되었다. 그 후로 책을 긴 텀을 두고 네다섯번 정독했다. 읽기 쉽고 가벼운 책이기도 하고, 경험치가 누적됨에 따라 새로 발견하는 것이 있었기 때문이다. 이 책은 우아한테크코스의 레벨1 필독서에 포함되어 있다. 블랙잭 미션을 마치고 충격과 실의에 빠져 는 생각에 책을 다시 펼쳤다. 그래서 이 글은 책의 전체 내용 보다 특정한 주제와 그에 따른 의견을 중심으로 쓰여졌음을 양해바란다. 내 블랙잭 미션은 왜 망했을까? 네오의 강의에서 을 배우고, 이 책을 다시 읽기 전까진 미션의 패인을 라 생각했었다. 만약 나와 비슷한 생각을 가진 사람이 있다면 흥미롭게 읽을 수 있을 것이다. 이 책을 읽기 전에… 무언가를 설명함에 있어 비유는 때때로 혼란을 일으킨다. 객체지향을 설명코자 나온 많은 비유가 오히려 입문자들에게 잘못된 관념을 심고 있다. 조부모-부모-자식과 자산의 흐름 또는 동물계의 분류와…

April 18, 2022
우아한테크코스
독서