← 목록으로
📅 2026.06.01
Java 코드 퀄리티를 높이는 개인 컨벤션과 유지보수 전략
JavaTechStudyCodeConventionLombok

본 문서는 실무에서 기술 부채를 줄이고 유지보수성을 극대화하기 위해 지켜야 할 Java 코드 작성 개인 컨벤션을 정리한 기록입니다.


1. 핵심 컨벤션 규칙 및 구체적 예시

① 무분별한 setter 사용 제한

로직 내에서 setter를 무분별하게 사용하면 객체의 상태 변경 추적이 불가능해지고, 모듈 및 패키지 간의 경계가 무너져 의존성이 파괴됩니다. 데이터 변경은 사전에 정의된 특정 비즈니스 위치나 지정된 규약이 있는 예외적인 케이스에서만 제한적으로 수행되어야 합니다.

  • 잘못된 접근: 외부 서비스나 컨트롤러 레이어에서 order.setStatus("CANCEL")를 직접 호출하여 도메인의 상태를 강제로 변경하는 경우, 취소 로직이나 검증 절차가 누락되어도 잡아내기 어렵습니다.
  • 올바른 제어: 객체 내부에서 상태 변경의 책임을 갖도록 캡슐화합니다.
// 외부에 setter를 노출하지 않고, 의도가 명확한 메서드만 제공
public class Order {
    private String status;
 
    public void cancel(CancelReason reason) {
        if (!"ORDERED".equals(this.status)) {
            throw new IllegalStateException("취소 가능한 상태가 아닙니다.");
        }
        this.status = "CANCEL";
        // 관련된 도메인 이벤트나 추가 로직을 여기서 일괄 처리
    }
}

② toString, equals, hashCode 메서드 재정의 지양

과거에는 객체 내부 변수 출력이나 값 기반의 동등성 비교를 위해 이 메서드들을 수동으로 오버라이드하곤 했습니다. 하지만 현대 개발 환경에서는 IDE 기능이나 외부 라이브러리가 이를 안정적으로 지원하며, 실무에서 커스텀 객체 자체를 직접 equals()로 비교하는 케이스는 극히 드묾니다.
따라서 무분별한 재정의는 지양합니다. 불가피하게 재정의를 해야 하는 상황이라면 발생 가능한 의존성 순환이나 프레임워크 매핑 리스크를 반드시 고려해야 합니다.

③ 지나친 수동적 코드 작성 지양

Getter, Setter, 생성자(Constructor) 같은 보일러플레이트 코드를 매번 수동으로 손코딩하는 방식은 지양합니다. 필드가 추가되거나 수정될 때마다 관련된 모든 메서드를 사람이 직접 수정해야 하므로 관리 공수가 커지고 휴먼 에러의 주원인이 됩니다. Lombok이나 Spring 어노테이션을 적극 활용해야 합니다.

④ 로그 작성 시 System.out 금지 및 로깅 프레임워크 활용

레거시 코드에서 흔히 보이는 System.out.println()을 통한 데이터 출력은 운영 환경에서 치명적입니다. 표준 출력은 로그 레벨 관리가 불가능하여 배포 후 불필요한 디스크 I/O를 유발하고, 로깅 관련 AOP를 통한 중앙 집중식 관리가 불가능해집니다.
반드시 로깅 프레임워크(Log4j2, Logback 등)를 사용해야 하며, 에러 로그 작성 시에는 예외 객체를 통째로 넘겨 StackTrace를 보존해야 합니다.

  • 올바른 로깅: log.error("주문 처리 중 예외 발생 - 사용자ID: {}", userId, e);
  • 이유: 로그 레벨에 따라 출력을 동적으로 제어할 수 있고, Throwable 객체가 그대로 전달되어 유실 없이 에러 추적이 가능합니다.

⑤ Maven, Gradle 의존성 버전 관리

프로젝트 의존성 라이브러리의 버전에 따라 알려진 보안 취약점(CVE)이 노출되거나 서로 간의 버전 호환성 충돌 문제가 발생합니다.
당장의 기능 개발에만 급급하여 버전을 방치하면, 추후 Java 버전을 업그레이드해야 하는 시점에 의존성 간의 얽힌 실타래 때문에 사이드 이펙트(Bomb)가 발생할 수 있습니다. 주기적으로 의존성 버전을 상시 최신화하여 기술 부채를 적시에 해소해야 합니다.


2. 아키텍처적 관점의 추가 보충

제시된 컨벤션은 시스템의 지속 가능성을 확보하기 위한 백엔드 개발자의 필수적인 기준입니다. 이를 프로덕션 환경에 적용할 때 함께 고려하면 좋은 확장 개념입니다.

① 불변성(Immutability)을 중심으로 한 캡슐화 디자인

무분별한 setter를 막는 것에서 나아가, 팩토리 패턴이나 빌더 패턴을 사용하여 객체 생성 시점에 모든 데이터를 주입하고 이후에는 상태를 변경할 수 없도록 '불변 객체'화하는 것을 권장합니다.
멀티스레드 환경인 Spring 백엔드 구조에서 객체의 불변성이 보장되면 동시성 이슈를 원천 차단할 수 있으며, 코드의 예측 가능성이 극대화됩니다.

② 로깅의 구조화와 파사드 패턴(SLF4J)의 활용

Log4j 등 특정 로깅 구현체를 코드에 직접 선언하여 사용하는 것보다, 자바 로깅의 표준 추상화 레이어인 SLF4J 인터페이스를 거쳐 사용하는 것이 좋습니다.
비즈니스 로직이 특정 프레임워크에 종속되는 것을 막아주며, 어노테이션 기반(@Slf4j)으로 로거 인스턴스 생성을 자동화하여 코드 작성을 더욱 간결하게 유지할 수 있습니다.
파사드 패턴도 이미 구현된 라이브러리를 통해 구현하는 것을 지향 합니다. 또는, Spring-boot 같은 프레임워크에서 지원하는 의존성 제품을 활용합니다.

③ 중앙 집중식 호환성 관리 (BOM 적용)

의존성 버전의 상시 최신화 과정에서 발생할 수 있는 라이브러리 간 버전 충돌을 방지하기 위해 빌드 도구의 BOM(Bill of Materials) 체계를 도입하는 것이 안전합니다.
Spring Boot의 Dependency Management 시스템처럼 이미 상호 호환성이 검증된 버전 세트를 일괄 적용함으로써, 개별 라이브러리를 업데이트할 때 발생하는 런타임 호환성 예외를 근본적으로 방지할 수 있습니다.