티스토리 뷰

반응형

개발을 하다 보면 코드가 점점 복잡해지고, 가독성이 떨어져서 수정하기가 곤란해지는 순간이 찾아온다. 특히 PHP로 구축된 프로젝트에서 여러 파일을 거쳐 오는 파라미터나 세션 처리 방식을 깔끔하게 정리하지 않으면, 디버깅과 유지 보수에 어려움을 겪게 된다. 이번 글에서는 PHP로 작성된 코드를 리팩토링하여 가독성을 높이고, 유지 보수성을 향상시키는 방법을 예시와 함께 살펴보고자 한다.

 


1. Null 병합 연산자를 활용한 파라미터 처리

기존에는 if (isset($_REQUEST['xxx'])) { $xxx = $_REQUEST['xxx']; } else { $xxx = ''; } 같은 방식을 사용했다면, PHP 7 이후부터 도입된 **Null 병합 연산자(??)**를 이용하면 보다 간결하게 코드를 작성할 수 있다. 예를 들어, _REQUEST 값을 받는 과정을 다음과 같이 단순화할 수 있다.

// before
if (isset($_REQUEST["search"])) {
    $search = $_REQUEST["search"];
} else {
    $search = '';
}

// after
$search = $_REQUEST['search'] ?? '';

이렇게 하면 파라미터가 존재하면 해당 값을, 존재하지 않으면 빈 문자열을 할당한다. 그 결과, 코드 라인이 줄어들고 조건문을 최소화해 가독성과 유지 보수에 유리해진다.


2. 날짜 처리 및 기본값 설정

웹 애플리케이션에서는 날짜 범위를 다룰 일이 잦다. 예를 들어, 조회 기간(fromdate, todate)을 사용자가 입력하지 않았을 때, 현재 연도의 시작일과 말일을 기본값으로 설정할 수 있다. 아래처럼 ??를 활용하면 간단히 처리 가능하다.

$fromdate = $_REQUEST['fromdate'] ?? '';
$todate   = $_REQUEST['todate']   ?? '';

if ($fromdate === '') {
    $currentYear = date('Y');
    $fromdate    = $currentYear . '-01-01';
}

if ($todate === '') {
    $currentYear = date('Y');
    $todate      = $currentYear . '-12-31';
    $Transtodate = strtotime($todate . '+1 days');
    $Transtodate = date('Y-m-d', $Transtodate);
} else {
    $Transtodate = strtotime($todate);
    $Transtodate = date('Y-m-d', $Transtodate);
}

이렇게 설정해 두면, 사용자가 날짜 범위를 입력하지 않았을 때도 코드가 의도대로 움직이며, 별도 에러 처리를 강제할 필요가 줄어든다. 무엇보다 어디서든지 명확하게 기본값을 파악할 수 있어 유지 보수가 한결 쉬워진다.


3. 배열 선언과 초기화 방식

PHP에서 배열을 다루는 것은 매우 직관적이지만, 종종 정의되지 않은 인덱스에 값을 대입하거나, 변수가 어디서 어떻게 초기화되는지가 불분명해져 혼란이 생길 수 있다. 아래 예시처럼 반드시 배열을 먼저 선언하고, 루프 내에서 값을 더하기 전에 isset 등을 통해 확인하는 습관을 들이면 오류를 줄일 수 있다.

$sum_title = [];
$sum       = [];

// 예시 루프
for ($i = 1; $i <= $rowNum; $i++) {
    // 아직 $sum[$i]가 정의되지 않았다면 초기화
    if (!isset($sum[$i])) {
        $sum[$i] = 0;
    }
    // 이후에 $sum[$i] += $someValue;
}

이렇게 명시적으로 배열을 초기화하면, 나중에 해당 변수가 어디서 어떻게 생성되었는지 정확히 추적 가능해진다. 이는 오류 발생을 예방하는 효과가 크고, 디버깅 시간을 절약해 준다.


4. SQL 쿼리와 예외 처리

PDO를 사용해 DB에 접근할 때에는 예외 처리 구문을 통해 예상치 못한 오류가 발생했을 때의 상황을 안정적으로 처리해야 한다. 아래와 같이 try - catch 구문을 이용하면, 오류 메시지를 확인하고 빠른 대응이 가능하다.

require_once($_SERVER['DOCUMENT_ROOT'] . "/lib/mydb.php");
$pdo = db_connect();

try {
    $sql  = "SELECT * FROM mirae8440.steelsource";
    $stmh = $pdo->query($sql);

    // 데이터 처리 로직
    while ($row = $stmh->fetch(PDO::FETCH_ASSOC)) {
        // ...
    }
} catch (PDOException $Exception) {
    print "오류: " . $Exception->getMessage();
}

실제 프로젝트에서는 예외 상황에서 단순히 오류를 출력하기보다는 로깅 시스템에 기록하거나, 사용자에게 안내 메시지를 보여주는 방식으로 확장할 수 있다. 이러한 구조를 미리 잡아두면, 에러 발생 시 대처 방안이 더욱 체계적이 된다.


5. 리팩토링된 예시 코드

위에서 살펴본 핵심 포인트를 모두 반영하면 코드는 아래와 같이 리팩토링할 수 있다. 가독성, 유지 보수성, 검색 및 확장을 고려한 최적화 방식을 확인해 보자.

<?php
// 파라미터 간단화
$search         = $_REQUEST['search']         ?? '';
$Bigsearch      = $_REQUEST['Bigsearch']      ?? '';
$separate_date  = $_REQUEST['separate_date']  ?? '';
$display_sel    = $_REQUEST['display_sel']    ?? 'doughnut';
$find           = $_REQUEST['find']           ?? '';
$mode           = $_REQUEST['mode']           ?? '';
$fromdate       = $_REQUEST['fromdate']       ?? '';
$todate         = $_REQUEST['todate']         ?? '';

// separate_date가 빈값이면 기본 '2'로 설정
if ($separate_date === '') {
    $separate_date = '2';
}

// 날짜 기본값 설정
if ($fromdate === '') {
    $currentYear = date('Y');
    $fromdate    = $currentYear . '-01-01';
}

if ($todate === '') {
    $currentYear = date('Y');
    $todate      = $currentYear . '-12-31';
    $Transtodate = strtotime($todate . '+1 days');
    $Transtodate = date('Y-m-d', $Transtodate);
} else {
    $Transtodate = strtotime($todate);
    $Transtodate = date('Y-m-d', $Transtodate);
}

// DB 연결
require_once($_SERVER['DOCUMENT_ROOT'] . "/lib/mydb.php");
$pdo = db_connect();

// steelsource 테이블 조회
$sql = "SELECT * FROM mirae8440.steelsource";
try {
    $stmh     = $pdo->query($sql);
    $rowNum   = $stmh->rowCount();
    
    $steelsource_num  = [];
    $steelsource_item = [];
    $steelsource_spec = [];
    $steelsource_take = [];
    
    $counter = 0;
    while ($row = $stmh->fetch(PDO::FETCH_ASSOC)) {
        $counter++;
        $steelsource_num[$counter]  = $row['num'];
        $steelsource_item[$counter] = $row['item'];
        $steelsource_spec[$counter] = $row['spec'];
        $steelsource_take[$counter] = $row['take'];
    }
} catch (PDOException $Exception) {
    print "오류: " . $Exception->getMessage();
}

// separate_date에 따라 날짜 컬럼 설정
$SettingDate = ($separate_date === '1') ? "outdate" : "indate";

// 조회 조건(where) 구문
$common = " WHERE (outdate BETWEEN DATE('$fromdate') AND DATE('$Transtodate')) 
            AND (which = '$separate_date')";

// steel 테이블에서 합계 계산
$sum_title = [];
$sum       = [];

$sql = "SELECT * FROM mirae8440.steel $common";
try {
    $stmh = $pdo->query($sql);
    while ($row = $stmh->fetch(PDO::FETCH_ASSOC)) {
        $item     = $row['item'];
        $spec     = $row['spec'];
        $steelnum = $row['steelnum'];
        $which    = $row['which'];

        $tmp = $item . $spec;
        for ($i = 1; $i <= $rowNum; $i++) {
            $sum_title[$i] = $steelsource_item[$i] . $steelsource_spec[$i];
            if ($which === '1' && $tmp === $sum_title[$i]) {
                if (!isset($sum[$i])) {
                    $sum[$i] = 0;
                }
                $sum[$i] += (int)$steelnum;
            }
        }
    }
} catch (PDOException $Exception) {
    print "오류: " . $Exception->getMessage();
}
?>

이렇게 정리하면, 중복되는 코드가 사라지고 한눈에 로직의 흐름을 파악하기 쉬워진다. 각각의 변수가 어떤 역할을 하는지 명확하게 드러나기 때문에, 프로젝트를 함께 진행하는 다른 개발자나 이후에 코드를 인수받는 사람에게도 큰 도움이 된다.


6. 리팩토링의 가치

코드를 리팩토링한다는 것은 단순히 ‘줄이기’가 아니라, 구조화된 설계를 통해 다음 단계로 나아갈 발판을 마련하는 행위라고 볼 수 있다. 특히 PHP는 웹 개발에 많이 쓰이는 언어인 만큼, 언제든 새로운 기능을 빠르게 붙이기 위해서는 모듈화와 확장성, 그리고 직관적인 코드가 필수적이다.

Null 병합 연산자처럼 편리한 문법을 적재적소에 적용하고, DB 연결이나 에러 처리 로직을 통일하면 전체적인 코드 품질이 크게 개선된다. 이러한 작업을 습관화하면 개발 효율이 높아지고, 특정 문제 발생 시에도 신속하게 해결할 수 있게 된다. 더불어 코드 리뷰와 협업 과정에서도 생산적인 논의가 이루어질 가능성이 커진다.


7. 마치며 드리는 팁

PHP 코드를 다룰 때에는 버전별로 문법 지원 여부가 다를 수 있다는 점에 주의해야 한다. 만약 서버 환경이 구버전 PHP라면, Null 병합 연산자 같은 문법이 동작하지 않을 수도 있다. 그렇기 때문에 프로젝트 시작 단계에서 PHP 버전을 확인하고, 최대한 최신 버전을 사용하는 것이 좋다.

이와 함께 객체지향 설계, MVC 패턴 적용, 코딩 컨벤션 통일 등의 원칙을 지키면, 장기적으로 더 큰 프로젝트에서도 안정적인 개발이 가능해진다. PHP 특유의 강점을 살려 빠른 프로토타이핑을 하되, 깔끔하고 일관성 있는 코드 스타일을 유지하는 습관을 들이는 것이 중요하다.

효율적인 리팩토링을 통해 웹 애플리케이션의 성능과 유지 보수성을 높여보자. 그리고 한 발 더 나아가, 테스트 자동화와 CI/CD 파이프라인 등을 구축해 배포 과정까지도 효율화한다면, 더욱 빠르고 안정적인 서비스를 제공할 수 있을 것이다.


위에서 살펴본 사례 외에도, 개발 환경에 따라 다양한 리팩토링 기법을 적용할 수 있다. 코드를 단순히 압축하는 데 그치지 않고, 어떻게 하면 협업자들이 구조를 한눈에 이해할 수 있을지, 또 어떠한 부분에서 가장 많은 시간이 소요되는지를 고민하며 개선 방향을 잡아 나가는 과정이 곧 고품질 서비스를 위한 핵심이라고 할 수 있다. PHP를 비롯한 웹 개발 언어 특성을 잘 이해하고, 현업에서 누적된 노하우를 녹여낸 리팩토링을 계속 시도해 보길 바란다.

반응형
댓글