전체 글(15)
-
T라 미숙해 (feat. 제네릭, 어디까지 써봤니?) - 3
T라 미숙해 (feat. 제네릭, 어디까지 써봤니?) - 1 T라 미숙해 (feat. 제네릭, 어디까지 써봤니?) - 1Event 페이지나 Lounge 페이지에서 일어나는 행위를 Log로 남겨야 하는 요구사항이 있었다. 여러 가지 방법이 있었겠지만, 계속 뒤바뀌는 상황에서 일단 RDB에 적당히 일반화된 포맷으로 저장하도록 zins.tistory.com T라 미숙해 (feat. 제네릭, 어디까지 써봤니?) - 2 T라 미숙해 (feat. 제네릭, 어디까지 써봤니?) - 2T라 미숙해 (feat. 제네릭, 어디까지 써봤니?) - 1 T라 미숙해 (feat. 제네릭, 어디까지 써봤니?) - 1Event 페이지나 Lounge 페이지에서 일어나는 행위를 Log로 남겨야 하는 요구사항이 있었다. 여러 가지 zins..
2024.09.09 -
T라 미숙해 (feat. 제네릭, 어디까지 써봤니?) - 2
T라 미숙해 (feat. 제네릭, 어디까지 써봤니?) - 1 T라 미숙해 (feat. 제네릭, 어디까지 써봤니?) - 1Event 페이지나 Lounge 페이지에서 일어나는 행위를 Log로 남겨야 하는 요구사항이 있었다. 여러 가지 방법이 있었겠지만, 계속 뒤바뀌는 상황에서 일단 RDB에 적당히 일반화된 포맷으로 저장하도록zins.tistory.com 도메인을 추상화하기 시작한 이유는 이를 활용하는 핵심 비즈니스 로직이 동일했기 때문이다. 도메인 설계만 하고 "어? 비슷하게 생겼네."하고 무턱대고 추상화하는건 불필요한 것 같다. 추상화는 잘못쓰거나 잘 못 쓸 경우, 그러니까 추상화된 대상의 내부 구성과 복잡도를 이해하지 못하면 오히려 비효율적인 코드가 된다.우리 팀의 상황은 예제를 기준으로 EmailSe..
2024.09.08 -
T라 미숙해 (feat. 제네릭, 어디까지 써봤니?) - 1
Event 페이지나 Lounge 페이지에서 일어나는 행위를 Log로 남겨야 하는 요구사항이 있었다. 여러 가지 방법이 있었겠지만, 계속 뒤바뀌는 상황에서 일단 RDB에 적당히 일반화된 포맷으로 저장하도록 결정했다. 하지만, EventLog와 LoungeLog는 굉장히 닮아있었고 심지어는 이들을 기록하는 비즈니스 로직마저 닮은 점이 많았다. 우리 팀은 Event와 Lounge를 Page라는 추상적인 개념으로 인식할 수 있었고, PageLog와 PageLogService 라는 추상화를 적용해 보기로 했다.다음 예제는 위 상황을 재현할 수 있도록 가정한 간단한 케이스이다. 도메인 지식이 있어야 하는 Page 개념 말고, 간단하게 Email과 Sms를 발송해야 한다는 경우로 간소화 해보자. 발송할 주소와 메시..
2024.09.08 -
Be Kind (feat. 클린 스프링: 스프링 개발자를 위한 클린코드 전략)
인프콘 2024, Toby님의 감상문 현업의 비즈니스는 시간만큼 빠르게 흘러간다.변화와 성장은 당연하고, 미래를 준비해야 하기도 한다. 과정에서의 우리는 어떤 모습인가? 이를테면 "클린 코드를 짜려면 생산성이 떨어져."라는 말을 따끔하게 짚어준 것이다.그 무엇도 우위에 있는 것은 없고, 주어진 비즈니스 요구사항처럼 반드시 고려해야 하는 핵심이다. 유지보수성이 좋은 클린 코드가 (아마도 핵사고날을 대표적인 예시로) 유명하다. 변경에 용이하고 효율적이기 때문에 구축 이후의 생산성이 좋다. 리팩터링 단계에서 생산성이 높으려면 변경에 의한 영향도를 파악할 수 있는 테스트 코드와 같은 보호장치가 필요하다. 그래서일까. TDD로 구성하는 클린 아키텍처 서버는 무척 이상적이기도, 완벽하기도 한 결론처럼 알려져..
2024.08.03 -
선배 Proxy 고려해서 equals 오버라이드 해주세요, 탕탕 후루후루~
CI에서만 test가 통과하지 않는 이상한 현상이 생겼다.해당 test code 파일만 돌렸을 땐, 우연히 A와 B의 id 값이 동일해서 통과했던 것이다.그러니까 A와 B를 equals 비교했을 때 통과하면 안 됐던 것이다. How? JPA Entity를 사용하면서 Id와 같은 공통 코드들을 상위로 끌어올리기 위해 BaseEntity를 다음과 같이 만들어뒀다. @MappedSuperclassabstract class BaseEntity( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id: Long? = null,) : Serializable { override fun equals(other: Any?): Boolean { ..
2024.07.26 -
Test Code 500개 도달 여정 (feat. DIP, 맞다이로 드루와)
3개월 전에 Test Code 100개를 겨우 넘기고 자랑스럽게 남긴 링띤 글. 지금은 두 명의 든든한 새 백엔드 팀원 Does, Kerry 도 합류하고 Test Code도 500개에 도달했다. 여기까지 오는 과정에서 참 많은 고민거리가 있었고, 재밌는 이슈들도 많았는데. 그중 가장 짜릿하다고 느낀 DIP 적용과 그로 인한 Test Code 이슈 해결 과정을 정리해보려 한다. 현재 우모(Umoh)의 모듈 구조를 간단하게 표현하면 비즈니스 도메인을 담은 common 모듈을 중심으로, batch/integration/core* 모듈이 있다. 그렇기 때문에 common 모듈은 integration 모듈을 알지 못한다. 그리고 integration에서 EmailSender가 구현되어 있다. *core: 모든 모..
2024.05.14