[React CS] 디자인 패턴 1 - Presentation&Container 패턴

2023. 11. 7. 22:39cs및 소프트스킬/react

728x90
반응형
SMALL

안녕하세요.

디자인 패턴을 알아보는 시간을 가집니다.

 

이번 시간에는 디자인 패턴을 사용하는 패턴 중 하나인 Presentation & Container 패턴의 대해서 알아봅니다.

 

보통 처음 시간에 배울 때 구조는 아래와 같은 구조로 사용하는데,

function 컴포넌트 () {
	/*
    	로직 구현
    */
    
    return (
    	<div> UI 출력 </div>
    )
}

 

 

이런 구조를 이용하여 사용을 하게 되실겁니다.

 

하지만, 매번 사용하다가 조금 더 클린화 된 코드를 작성하고, 로직 컴포넌트와 View 컴포넌트로 나눠서 작성하는 것을 생각을 해낸 결과 디자인 패턴으로 쓰이는 Presentation & Container 디자인 패턴을 이용하여 사용 방법으로 활용하여 사용이 가능하다는 것을 알게 되었습니다.

 

 

따라서 Presentation & Container 패턴을 적용 전과 적용 후의 대해서 구조를 먼저 살펴 보겠습니다.

 

디자인 패턴(Presentation&Container) 적용 전과 후

 

 

 

변경 전 : Origin Compnent - Logic과 UI를 컴포넌트를 이룬다.

변경 후 : Presiontation Component - UI 컴포넌트만 구성, Conatiner Component - 로직 부분만 구성

 

 

적용 전

<Origin Component 소스 구성 요소>

import React, { KeyboardEvent, useEffect, useState } from 'react'
import Presentation from './Presentation'

// 인터페이스 설정 - 이름
type NameInterface = {
  name: string
}

// 인터페이스 설정 - 나이
type AgeInterface = {
  name: string
}


// Container 컴포넌트 - 로직 처리
const Container = () => {
  // 일반적, 컴포넌트 구현
  // 처음 배울때, return 안에 있는 건 view단을 출력, return 바깥은 로직 표현
  const [name, setName] = useState<NameInterface>();
  const [age, setAge] = useState<AgeInterface>();

  const onNameChange = (e:any) => {
    const {name, value} = e.currentTarget;
    setName({
      [name] :value
    } as NameInterface)
  }
  
  const onAgeChange = (e:any) => {
    const {name, value} = e.currentTarget
    setAge({
      [name]: value
    } as AgeInterface)
  }

  // 테스트용
  useEffect(() => {
    console.log(name)
    console.log(age)
  }, [name, age])

  return (
    <Presentation 
      onNameChange={onNameChange}
      onAgeChange={onAgeChange}
    />
  )
}

export default Container

 

 

 

 

적용 후

<Presentation Component>

// 상속 설정
type ViewInterface= {
  onNameChange: any,
  onAgeChange: any
}

// Presentation 컴포넌트
// View만 처리
const Presentation = (props:ViewInterface) => {
  const {onNameChange, onAgeChange} = props;

  return (
    <div>
      <form>
        <label>이름</label>
        <input type="text" name="name" onChange={onNameChange}></input>
        <br/>
        <label>나이</label>
        <input type="text" name="age" onChange={onAgeChange}></input>
      </form>
    </div>
  )
}

export default Presentation

 

 

<Container Component>

import { useEffect, useState } from 'react'
import Presentation from './Presentation'

// 인터페이스 설정 - 이름
type NameInterface = {
  name: string
}

// 인터페이스 설정 - 나이
type AgeInterface = {
  name: string
}


// Container 컴포넌트 - 로직 처리
const Container = () => {
  const [name, setName] = useState<NameInterface>();
  const [age, setAge] = useState<AgeInterface>();

  const onNameChange = (e:any) => {
    const {name, value} = e.currentTarget;
    setName({
      [name] :value
    } as NameInterface)
  }
  
  const onAgeChange = (e:any) => {
    const {name, value} = e.currentTarget
    setAge({
      [name]: value
    } as AgeInterface)
  }

  // 테스트용
  useEffect(() => {
    console.log(name)
    console.log(age)
  }, [name, age])

  return (
    <Presentation 
      onNameChange={onNameChange}
      onAgeChange={onAgeChange}
    />
  )
}

export default Container

 

 

 

실행 결과

 

 

 

디자인 패턴으로 리팩토링 한 경우 결과를 비슷하게 적용 할 수 있습니다.

728x90
반응형
LIST