코드 리팩토링(1)

승환·2025년 1월 19일

📌 코드 리팩토링?

코드 리팩토링은 기존 코드의 동작을 바꾸지 않고 구조와 가독성을 개선하는 과정을 말한다.
코드 품질을 높이고 유지보수성을 향상시키는 것에 목적이 있다.


📌 리팩토링을 하는 코드와 그 이유

코드중에 이런 코드가 있었다.

-- WITH RECURSIVE를 사용하여 재귀 쿼리 작성
WITH RECURSIVE EmployeeHierarchy AS (
    -- Anchor 쿼리: 최상위 직원 (ManagerID가 NULL인 직원)
    SELECT 
        EmployeeID,
        Name,
        ManagerID,
        1 AS Level
    FROM Employees
    WHERE ManagerID IS NULL
    
    UNION ALL
    
    -- 재귀 쿼리: 하위 직원 탐색
    SELECT 
        e.EmployeeID,
        e.Name,
        e.ManagerID,
        eh.Level + 1 AS Level
    FROM Employees e
    INNER JOIN EmployeeHierarchy eh
        ON e.ManagerID = eh.EmployeeID
)
-- 결과 조회
SELECT * 
FROM EmployeeHierarchy
ORDER BY Level, EmployeeID;

정확히 원본 코드는 아니지만 최상위 직원을 찾아서 트리를 구성하는 재귀 탐색 SQL탐색문이다.

이렇게 구성하면 SQL을 본래 알던 사람도 다른 사람의 코드를 보면 한번에 이해하기 힘들다는
단점이 있다. 이는 곧 유지보수의 문제가 있다는 단점으로 갈 수 있기 때문에 좋지 못한 코드가 된다.

그런문제도 있지만 가장 큰 문제점은 재귀 탐색을 하고 있어서 성능의 문제가 있다는 것이다.


📌 해결 아이디어

기본적인 아이디어 흐름은 먼저 재귀 탐색을 없애는 것이다.
SQL에서 재귀탐색을 통해 트리를 구성하고 밖에 나와서 또 재귀탐색을 통해 트리를 내보내는 형태인 코드를 재귀 탐색을 완전히 없애는 것이 목적이다.

-> 쿼리를 이용해서 재귀 탐색을 진행하니까 쿼리를 쓰지 않고 트리를 구성하면 되지 않을까?
현재 파일 구성은 mapper을 이용해서 DB를 커넥션해서 불러오고 있다. 이 과정에서 Xml파일에 SQL이 담기고 그걸 이용해서 트리를 만들고 있다.

-> 이 방법을 사용하지 않으려면?
Mapper로 불러오는 방법 대신 다른 방법을 사용해야 한다. -> Jpa를 통해 불러오자

@Repository
public interface TestRepository extends JpaRepository<MyEntity, Long>{
   List<MyEntity> findBySeq(Long Seq);
}

이런 식으로 불러올수 있다. Jpa에 대한 설명은 다른 포스트에 하도록 한다.

여기서 MyEntity는 엔티티 객체이다. 이 엔티티 객체가 곧 DB커넥션을 통해 값을 가져올 수 있는
중간 매계가 된다.

-> 어떤 방식으로 불러오는것일까? 순서가 어떻게 될까
Jpa를 통해 DB에서 값을 불러오고 Controller에 그 값을 전달한 후에 적절한 처리를 통해 트리를 구성해서 Json으로 반환하면 되겠다.

-> 기준 키가 무엇일까?
이걸 알려면 일단 DB에서 어떻게 데이터를 전달하는지 알아야 했다.

{
    "seq": 719,
    "parentSeq": 713,
    "companySeq": 197,
    "depth": 4,
    "name": "기술연구소",
    "status": "A",
    "regId": "string",
    "regDate": "2024-08-26T00:42:18.859+00:00",
    "modId": "",
    "sort": 0
  }

이런 형식으로 불러온다는 것을 알게 되었다.
그럼 아까 Jpa를 통해 depth가 10인 필드부터 불러올 수 있겠다.
-> 근데 이렇게 하면 SQL호출을 해야해서 JPQL을 사용하거나 따로 쿼리문을 작성해서 Mapper을 써야한다.

우리가 원하는 방식은 Jpa를 사용해서 불러오는 것이기 때문에 일단 모든 값을 불러오고
그 값을 정리하는 방식을 써야겠다.

-> 그럼 기준을 어떻게 잡아야 할까?
자세히 보니까 companySeq라는 부분이 모든 json에서 동일한 것을 확인하였다.
따라서 companySeq로 일단 모든 트리 객체를 불러올 수 있을 것 같다.

-> 그럼 모두 뽑은 후에는 어떻게 정렬해야 할까?
트리의 구조를 만드는 것에는 위에서 내려오는 방법도 있지만 아래에서 모든 것을 통합해서 올리는 방법도
있다. 이 방법을 사용할 것이다.
우선순위 큐를 사용해서 Depth를 높은 순(10~0) 순으로 정렬하고 알고리즘을 짜면 되겠다.

->알고리즘 순서

  1. Jpa로 모든 트리 요소를 불러와서 List에 담는다.
  2. 우선순위 큐안에 depth가 높은 순서대로 정렬한다.
  3. 큐 안에서 하나를 뽑아서 트리노드 하나로 만든다.
  4. 그 노드는 depth가 가장 높은 가장 하위 객체일 것임
  5. 큐가 빌 때까지 아래 과정을 반복한다.
    5-1. depth비교 후같다면
    5-2. Map에 키가 존재한다면 이미 등록된것임으로 추가하고
    5-3. 키가 존재하지 않는다면 새로운 키임으로 하나를 만들어서 Map에 넣는다.
  6. 이런 과정을 반복해서 하나의 depth가 끝난다면 모아놓은 데이터를 모두 부모 객체에 전달하고 부모를 추가한다.
  7. depth가 0이 나오면 모든 객체를 전부 넣어서 트리를 마무리한다.

이렇게 쓰면 좀 이해가 어렵다. 요는 아래서부터 트리를 만드는 것인데 그림을 참고하자

부모가 같은 노드를 삽입할 때

부모가 다른 노드를 삽입할 때 depth가 같다면

depth가 다른 노드를 삽입할 때


이런 형식으로 작동하게 된다. 일단 아이디어는 이렇고 다음 포스트에서는 코드를 다루겠다.

profile
왕초보 학부생

0개의 댓글