[Wecode] Layered Pattern

김택수·2022년 10월 9일
1

Layered Pattern 관련하여 같이 공부하는 동기분들과 나누고 정리했던 이야기를 더 일목요연하게 공유하고자 글을 작성함.

Layered Pattern 이란 서버단에서 사용할 수 있는 Design Pattern 중에 하나로 간단하게는 Router를 통해 요청을 분기시키고, Controller에서 데이터의 유무를 판단하여 들어온 데이터를 Service로 보내주고, Service에서 로직을 수행 한 후 Dao로 건너가 쿼리문을 수행하는 일련의 과정이다.

처음 하나의 파일에 모든 것들을 넣고 코딩할때와는 다르게 어디에서 어떤 것을 사용하여 구현해야하는지 명확했고, 모든것이 독립적으로 움직이고 C - S - D가 서로 다음 순서의 Layer만 의존하고 있기 때문에 에러상황에서도 어디에서 무엇이 에러였는지 빠르게 유추할 수 있고 해결해 나갈 수 있었다.

하지만 문제는 코드 상으로 Dao에서 쿼리문으로 나온 결과값을 클라이언트단에 return 해주는 과정이 이해가 잘 가지 않았다. 분명 Dao까지 내려가는 코드를 작성했을 뿐인데 클라이언트단에 값이 return이 되는 현상이 일어났기 때문인데, 이 내용을 중점적으로 공유하려고 한다.

// Dao.js

// 원래 코드
const daoAllPosts = async () => {
  const data = await myDataSource.query(
    `SELECT 
        u.id as userId,
        u.profile_image as userProfileImage,
        p.id as postingId,
        p.posting_image_url as postingImageUrl,
        p.content as postingContent 
    FROM users as u, posts as p
    `
  );
  return data;
  
// 이해하기 쉬운 코드
const daoAllPosts = async () => {
  const data = Query문에 대한 결과
  );
  return data; // Query문에 대한 결과를 return한다
 // Query문에 대한 결과를 data에 담고 daoAllPosts가 어디에선가 실행될 때 그 값으로 data를 받을 수 있다.
};
  1. Dao에서 모든 게시글을 불러오는 Query문을 작성해서 결과를 받고 그 결과를 data라는 변수에 담아 return 한다.
    여기서 중요하게 파악해야 할 점은, DaoAllPosts라는 함수를 module로써 exports 해놓으면 API 내 어디에서든 사용이 가능하다는 점이고, 이 점을 이용해서 Service에서 daoAllPosts라는 함수를 실행했을 때 우리가 data라는 변수에 담은 Query문에 대한 결과(모든 게시글)를 받아낼 수 있다.

    결론적으로는 이 단계에서는 Dao에서 특정 데이터를 받아내는 함수를 만들어 그 안에 로직을 채우고 그 로직의 결과를 변수에 담아 해당 함수에서 그 변수를 Return한다.(즉, 이 함수를 실행하면 로직의 결과를 반환 받을 수 있다.) 그 이후 export해서 다른 파일에서도 사용가능하게 만들어주고, Service에서 그 함수를 실행해 로직의 결과를 받을 수 있다는 점을 파악해야한다.

// Service.js

// 원래 코드
const ServiceAllPosts = async () => {
  return await Dao.daoAllPosts();
};

// 이해하기 쉬우라고 적은 코드
const ServiceAllPosts = async () => {
  return await Dao에서 만든 allposts의 return}
// 어디선가 allPosts라는 ServiceAllPosts라는 함수를 실행하면, Dao에서 만든 daoAllposts에 대한 return값을 받을 수 있고, 이 return값은 우리가 원하는 데이터를 뽑는 Query문의 결과이다.
  1. Service에서도 똑같이 allPosts라는 함수를 만들고(똑같을 필요없음.) 아직까진 비즈니스 로직이 없고 오로지 모든 게시글을 보고 싶다는 요청일 뿐이니 바로 return을 해주는데, 그 return값으로 이 전에 Dao에서 우리가 만든 데이터가 담긴 변수를 return 하는 allPosts 함수를 실행시켜서 Service의 allPosts 함수를 어디선가 실행했을 때, dao의 allPosts 함수의 결과값을 받도록 해준다.
// Controller.js

// 원래 코드
const allPosts = async (req, res) => {
  try {
    const data = await postService.allPosts();
    return res.status(200).json({
      data,
    });
  } catch (error) {
    return res.status(error.statusCode || 500).json({ message: error.message });
  }
};

// 쉽게 적은 코드
const allPosts = async (req, res) => {
  try {
    const data = Dao단에서 부터 Service를 거쳐 올라온 dao에서 Query문에 대한 결과값
    return res.status(200).json({
      data, // 그 결과값을 클라이언트에게 반환.
    });
  } catch (error) {
    return res.status(error.statusCode || 500).json({ message: error.message });
  }
};
  1. try catch문은 신경쓰지 않아도 되고, 중요한 것은 Dao에서 Service를 거쳐 올라온 Query문에 대한 결과값을 다시 data에 담는다. 이유는 그냥 식만 존재할 때는 값을 전달은 받았으나 그 값을 다시 어딘가에서 사용할 수는 없기 때문에 data라는 변수에 담아 사용가능하게 만들어주고 data라는 변수를 res.json을 통해 반환하여 클라이언트가 결국에는 Dao에서 올라온 결과값을 받아볼 수 있게 해준다.
profile
개발자 키우기 Lv1

4개의 댓글

comment-user-thumbnail
2022년 10월 9일

정리를 잘 해주셔서 많은 도움이 되었습니다!

1개의 답글
comment-user-thumbnail
2022년 10월 13일

갓택수님, 정말 많은 도움 되었습니다

1개의 답글