프로젝트

개인정보-컴플라이언스-웹애플리케이션 (수정사항 2-2)

알럽유 2025. 1. 29. 17:45
728x90

현재 아직도 JOIN이 여러 개의 평가 결과(assessment_result)가 있는 경우 중복된 시스템을 여러 번 조회하게 만드는 원인이 되고 있어.

 

수정전 코드

/**
 * 🔹 전문가가 배정된 시스템 목록 조회
 */
const getAssignedSystems = async (req, res) => {
  const { expertId } = req.query;

  console.log("✅ [getAssignedSystems] Received expertId:", expertId);

  if (!expertId) {
    return res.status(400).json({
      resultCode: "F-1",
      msg: "전문가 ID가 필요합니다.",
    });
  }

  try {
    const query = `
        SELECT s.id AS system_id, s.name AS system_name, u.institution_name, 
               ar.score, ar.grade, ar.feedback_status
        FROM assignment a
        JOIN systems s ON a.systems_id = s.id
        JOIN User u ON s.user_id = u.id
        LEFT JOIN assessment_result ar ON s.id = ar.system_id
        WHERE a.expert_id = ?;
      `;

    console.log("🟡 [getAssignedSystems] Running query:", query);

    const [results] = await pool.query(query, [expertId]);

    console.log("✅ [getAssignedSystems] Query results:", results);

    res.status(200).json({
      resultCode: "S-1",
      msg: "매칭된 시스템 조회 성공",
      data: results,
    });
  } catch (error) {
    console.error(
      "❌ [getAssignedSystems] 배정된 시스템 조회 실패:",
      error.message
    );
    res.status(500).json({
      resultCode: "F-1",
      msg: "서버 오류 발생",
      error: error.message,
    });
  }
};

 

🔍 문제의 원인

현재 JOIN이 assessment_result 테이블을 LEFT JOIN하고 있어서 system_id가 같은 데이터가 여러 개 존재할 경우 중복이 발생할 수 있습니다.
assessment_result에 같은 system_id에 대해 여러 개의 결과가 있으면 각 결과마다 한 번씩 시스템이 반복적으로 조회됩니다.

 

수정 코드

/**
 * 🔹 전문가가 배정된 시스템 목록 조회 (최신 평가 결과만 가져오기)
 */
const getAssignedSystems = async (req, res) => {
  const { expertId } = req.query;

  console.log("✅ [getAssignedSystems] Received expertId:", expertId);

  if (!expertId) {
    return res.status(400).json({
      resultCode: "F-1",
      msg: "전문가 ID가 필요합니다.",
    });
  }

  try {
    const query = `
      SELECT 
        s.id AS system_id, 
        s.name AS system_name, 
        u.institution_name, 
        ar.score, 
        ar.grade, 
        ar.feedback_status
      FROM assignment a
      JOIN systems s ON a.systems_id = s.id
      JOIN User u ON s.user_id = u.id
      LEFT JOIN assessment_result ar 
        ON s.id = ar.system_id 
        AND ar.completed_at = (
          SELECT MAX(completed_at) 
          FROM assessment_result 
          WHERE system_id = s.id
        )
      WHERE a.expert_id = ?;
    `;

    console.log("🟡 [getAssignedSystems] Running query:", query);

    const [results] = await pool.query(query, [expertId]);

    console.log("✅ [getAssignedSystems] Query results:", results);

    res.status(200).json({
      resultCode: "S-1",
      msg: "매칭된 시스템 조회 성공",
      data: results,
    });
  } catch (error) {
    console.error(
      "❌ [getAssignedSystems] 배정된 시스템 조회 실패:",
      error.message
    );
    res.status(500).json({
      resultCode: "F-1",
      msg: "서버 오류 발생",
      error: error.message,
    });
  }
};

 

✅ 개선된 점

중복 문제 해결


각 시스템에서 가장 최근(MAX(completed_at)) 평가 결과만 조회됩니다.
assessment_result에 system_id가 중복되어 있어도 최신 완료된 평가만 가져옵니다.

 

GROUP BY 없이도 최신 데이터만 가져올 수 있습니다.
GROUP BY를 사용하면 일부 DB에서 성능 저하가 발생할 수 있지만,
LEFT JOIN ... AND ar.completed_at = (SELECT MAX(completed_at)...) 방식은 각 시스템별로 최신 데이터를 가져오는 데 최적화됩니다.