ArchUnit 슬라이스 순환 의존성 검증으로 아키텍처를 코드로 강제한다
아키텍처 규칙은 대부분 문서에만 있다. “슬라이스 사이에는 순환 의존을 두지 않는다”고 적어 놓고, 코드 리뷰에서 걸러 내기를 기대한다. 그런데 리뷰어가 놓치면 그대로 들어가고, 한 번 들어간 순환 의존은 시간이 지날수록 걷어 내기 어려워진다 결론부터 말하면 이런 규칙은 테스트 코드로 강제할…
아키텍처 규칙은 대부분 문서에만 있다. “슬라이스 사이에는 순환 의존을 두지 않는다”고 적어 놓고, 코드 리뷰에서 걸러 내기를 기대한다. 그런데 리뷰어가 놓치면 그대로 들어가고, 한 번 들어간 순환 의존은 시간이 지날수록 걷어 내기 어려워진다 결론부터 말하면 이런 규칙은 테스트 코드로 강제할…
테스트 픽스처를 열어 보면 이런 코드가 있다 닉네임은 KimWhat이고 비밀번호는 verysecret이다. 이 값이 무슨 의미인지는 아무도 설명하지 않는다. 그냥 형식 검증을 통과할 만한 길이로 아무렇게나 정한 값이다. 그런데 이 값은 검증 코드에도 그대로 박혀 있다 이 테스트가 통과한다고 해서 비밀번호…
애플리케이션 서비스 클래스를 하나 열어 보면 이런 상태가 되어 있다 네 줄 모두 이 클래스가 무슨 일을 하는지에 대한 설명이 아니다. 스프링 빈으로 등록하고, 트랜잭션을 걸고, 파라미터 검증을 켜고, 생성자를 만들어 달라는 지시다. 애플리케이션 서비스를 새로 만들 때마다 이 네…
헥사고날 아키텍처를 배우고 나면 안과 밖의 경계는 선명해진다. 어댑터는 밖에, 도메인은 안에. 포트로만 소통한다. 그런데 정작 실무에서 막히는 지점은 그 다음이다. 회원 하나만 있을 때는 헥사곤 하나로 충분했는데, 강사가 들어오고 강의가 들어오면 헥사곤 안쪽이 금세 뒤엉킨다. 여기서 자연스럽게 떠오르는 발상이…
Member 엔티티가 있으니 MemberService 하나, MemberController 하나. 스프링을 배우면 대부분 이 구조로 시작한다. 처음에는 편하다. 문제는 N개월 뒤에 온다. MemberService는 메서드 열다섯 개짜리 클래스가 되고, 그것을 주입받은 코드만 봐서는 무슨 목적으로 쓰는지 알 수 없다. 헥사고날 아키텍처는 이 지점에서 다른…
MemberRegisterRequest 같은 요청 오브젝트를 어느 계층에 둘지 물으면, 개발자가 반사적으로 “애플리케이션 레이어”라고 답한다. DTO는 데이터를 담아 계층 경계를 넘기는 역할이니 서비스 레이어에 두는 것이 자연스럽다는 이유다. 그런데 헥사고날 아키텍처로 회원 등록 기능을 만들 때, 이 오브젝트를 도메인 레이어에 두었다. 결론부터…
기존 커맨드 패턴의 한계 이전 버전(V5)에서는 커맨드 패턴 기반의 서블릿을 사용했다. 각 URL 경로마다 별도의 서블릿 클래스를 만들고, 이를 ServletManager에 일일이 등록해야 했다 이 방식에는 두 가지 명확한 단점이 있다 기능이 수십 개로 늘어난다면? 클래스 파일과 매핑 코드가 함께 폭발적으로…
리플렉션이 필요한 이유 커맨드 패턴으로 서블릿을 구현할 때 흔히 부딪히는 두 가지 불편함이 있다 기능 하나당 클래스 하나 – 클래스가 폭발적으로 늘어난다 반면 아래처럼 하나의 컨트롤러에 여러 기능을 모을 수 있다면 훨씬 깔끔해진다 URL 경로 /site1이 들어오면 site1() 메서드를 이름으로…
왜 분리가 필요한가? 이전 버전의 HttpRequestHandler를 보면 문제가 바로 보인다 home(), site1(), site2(), search() 같은 서비스 로직이 서버 코드 안에 직접 박혀 있다. 다른 프로젝트에서 이 서버를 재사용하려면? 이 로직들을 전부 갈아엎어야 한다. 재사용이 불가능하다. 해결책은 명확하다. 서버가 해야 할…
왜 객체로 만드는가 HTTP 메시지는 명확한 규칙을 가진다 이 규칙이 존재한다는 것은 구조화할 수 있다는 의미다. 문자열을 매번 직접 파싱하는 대신, HttpRequest, HttpResponse 객체로 캡슐화하면 코드의 복잡도가 극적으로 줄어든다 HttpRequest – 요청 파싱 생성자에서 BufferedReader를 받아 시작 라인 → 헤더…