본문으로 건너뛰기
안동민 개발노트 아이콘

안동민 개발노트

본문 시작
2장 : 객체지향 설계와 Spring

BoardConfig 객체 조립

객체 생성과 구현 선택을 구성 루트에 모아 회원가입·로그인 서비스가 공유하는 객체 그래프를 한곳에서 읽습니다.

생성자 주입을 적용하면 서비스는 구현을 선택하지 않습니다. 프로그램 시작 지점에서 객체를 만들고 연결하는 코드를 한곳에 모읍니다. BoardConfig는 업무를 수행하지 않고 객체 그래프만 만듭니다.


구성 루트

board-core/src/main/java/board/BoardConfig.java
package board;

import board.member.*;

public final class BoardConfig {
    private final MemberRepository members =
            new MemoryMemberRepository();
    private final PasswordHasher passwordHasher =
            new TestPasswordHasher();

    public MemberRegistrationService memberRegistrationService() {
        return new DefaultMemberRegistrationService(
                members, passwordHasher);
    }

    public LoginService loginService() {
        return new LoginService(members, passwordHasher);
    }
}

회원가입과 로그인은 같은 회원 저장소와 해시 구현을 사용합니다. 두 서비스가 서로를 직접 생성하지 않고 구성 루트가 각각 완성된 객체를 제공합니다.

실행 코드

BoardApplication.java
public final class BoardApplication {
    public static void main(String[] args) {
        var config = new BoardConfig();
        var registration = config.memberRegistrationService();
        var login = config.loginService();

        Member member = registration.register(new SignUpCommand(
                "member@example.com", "안동민", "secret-1234"));
        long loginMemberId = login.authenticate(
                "member@example.com", "secret-1234");

        System.out.println("registered=" + member.id());
        System.out.println("login=" + loginMemberId);
    }
}

main은 Map 저장 방식이나 해시 문자열 형식을 모릅니다. 실행 진입점은 완성된 사용 사례를 호출할 뿐입니다.

객체 생성과 업무 실행 구분

객체책임바뀌는 이유
DefaultMemberRegistrationService중복 확인·해시·저장 순서회원가입 규칙 변경
MemoryMemberRepository메모리에 회원 저장저장 기술 변경
PasswordHasher 구현비밀번호 해시·비교보안 정책 변경
BoardConfig구현 선택과 연결실행 환경 변경

이 표의 변경 이유가 섞이면 다시 경계를 검토합니다.

테스트 구성

테스트는 BoardConfig를 통하지 않고 필요한 가짜를 직접 전달할 수 있습니다. 반대로 실제 실행 그래프가 올바른지는 구성 테스트 한 곳에서 확인합니다.

BoardConfigTest.java
@Test
void 회원가입과_로그인은_같은_회원_저장소를_사용한다() {
    var config = new BoardConfig();
    config.memberRegistrationService().register(new SignUpCommand(
            "member@example.com", "회원", "secret-1234"));

    assertThat(config.loginService().authenticate(
            "member@example.com", "secret-1234")).isPositive();
}

다음 문서에서는 구성 메서드가 매번 새 저장소를 만들 때 발생하는 공유 실패와 객체 수명을 다룹니다.