반응형
예제에 대한 전체 코드는 https://github.com/minseokLim/practice/tree/main/design-pattern에서 확인할 수 있다.

 

파사드 패턴(Facade pattern)은 여러 개의 클래스나 서브시스템을 감싸는 단일 인터페이스를 제공하여, 클라이언트가 복잡한 서브시스템과 상호작용 하는 것을 쉽게 만들어주는 패턴이다.

 

예제를 통해 좀 더 자세히 이 패턴에 대해 알아보자. 예제는 코틀린으로 작성하였다.

 

만약 한 사원에 대한 보고서를 생성해야하는 상황이 생겼다고 가정하자. 이 보고서는 사원 정보(Emp), 이력서 정보(Resume), 동료 평가 정보(Evaluation)를 바탕으로 생성된다. 이 3가지 정보는 각각의 DB 테이블에 저장되어있고, 각각 DAO 클래스를 제공한다. 아래 코드는 각각의 DAO를 감싸는 파사드 클래스의 예시이다.

class EmpReportDaoFacade(
    private val empDao: EmpDao,
    private val resumeDao: ResumeDao,
    private val evaluationDao: EvaluationDao
) : EmpReportFacade {
    override fun select(id: Int): EmpReport {
        val emp = empDao.select(id) ?: throw IllegalArgumentException("No employee found for id $id")
        val resume = resumeDao.select(id) ?: throw IllegalArgumentException("No resume found for id $id")
        val evaluation = evaluationDao.select(id) ?: throw IllegalArgumentException("No evaluation found for id $id")

        return EmpReport(
            employeeId = emp.id,
            employeeName = emp.name,
            phone = resume.phone,
            address = resume.address,
            evaluationGrade = evaluation.grade,
            evaluationComment = evaluation.comment
        )
    }
}

이렇게 하면 사용자는 각각의 DAO에 접근하는 대신, 파사드를 통해서 원하는 데이터를 얻을 수 있다. 보고서 정보를 원하는 곳이 여러 곳일 경우 코드 중복을 방지할 수 있다.

 

위 코드에서는 EmpReportDaoFacade가 EmpReportFacade 인터페이스를 구현하고 있다. 인터페이스를 따로 정의하면, 클라이언트의 변경 없이 서브시스템 자체를 변경할 수 있다는 장점이 있다. 위 예제에서 만약 관련 정보를 DB 테이블에서 직접 조회하는 것 대신, HTTP 요청을 통해 조회하는 것으로 변경되었다고 가정하자. 아래와 같이 EmpReportFacade 인터페이스를 구현하는 또 다른 파사드 클래스를 만들어주면, 클라이언트 코드의 변경 없이 대응이 가능하다.

class EmpReportHttpFacade(
    private val empHttpClient: EmpHttpClient,
    private val resumeHttpClient: ResumeHttpClient,
    private val evaluationHttpClient: EvaluationHttpClient
) : EmpReportFacade {
    override fun select(id: Int): EmpReport {
        val emp = empHttpClient.get(id) ?: throw IllegalArgumentException("No employee found for id $id")
        val resume = resumeHttpClient.get(id) ?: throw IllegalArgumentException("No resume found for id $id")
        val evaluation = evaluationHttpClient.get(id) ?: throw IllegalArgumentException("No evaluation found for id $id")

        return EmpReport(
            employeeId = emp.id,
            employeeName = emp.name,
            phone = resume.phone,
            address = resume.address,
            evaluationGrade = evaluation.grade,
            evaluationComment = evaluation.comment
        )
    }
}

 

 

이 글은 "객체 지향과 디자인 패턴 - 최범균" 책을 기반으로 작성되었다.

반응형

+ Recent posts