백엔드에서 코드 품질은 “구현 로직”만으로 결정되지 않습니다. 실제로 협업과 유지보수에서 더 큰 비용을 만드는 건 메서드 내부가 아니라 메서드의 입구(파라미터)와 출구(반환/예외)인 경우가 많습니다.
시그니처는 작은 단위의 API입니다. 즉, 좋은 시그니처는 호출자의 실수를 줄이고, 테스트/확장/리팩터링을 쉽게 만듭니다.
Java 기준으로 “오버로딩(overloading)”에서 시그니처가 핵심이 됩니다. 같은 이름의 메서드라도 파라미터 목록이 다르면 다른 메서드로 구분됩니다.
그리고 실무적으로는 “시그니처 = 계약”이라는 관점이 더 중요합니다. 파라미터 타입과 반환 타입, 예외/널 정책 같은 것들이 호출 패턴을 고정시키기 때문입니다.
“좋은 구현은 바꿀 수 있지만,
나쁜 시그니처는 팀 전체의 시간을 갉아먹는다.”
// (1) null 반환: 호출자가 null 처리 책임을 떠안음
User findUser(String userId);
// (2) Optional: “없을 수 있음”을 타입으로 강제
Optional<User> findUser(String userId);
// (3) 예외: “없음”을 예외로 취급 (서비스 정책에 따라 선택)
User getUserOrThrow(String userId) throws UserNotFoundException;
백엔드에서는 (3)처럼 “없음”을 예외로 올려 트랜잭션 롤백/에러 응답과 연결하는 경우가 많습니다. 반대로 (2)는 “없음도 정상 흐름”인 검색/필터 같은 경우에 안정적입니다.
👍 GOOD
- “없을 수 있음/필수”가 반환 타입으로 드러남(Optional/예외)
- 파라미터가 과하지 않고 의미가 명확함(VO/DTO로 묶임)
- 부작용이 있으면 이름에 암시됨(create, update, delete)
- 실패 조건(검증/권한/중복)이 예측 가능함
👎 BAD
- boolean/0/1 같은 “의미 없는 반환”으로 실패 원인을 숨김
- 파라미터가 너무 많아 호출이 취약함(순서 실수, 옵션 누락)
- 내부 구현 디테일(DB 컬럼/엔티티)을 그대로 노출
- 예외/널 정책이 메서드마다 제각각(일관성 붕괴)
💡 TIP / “시그니처는 곧 API 버전”이다
외부 API만 버전이 있는 게 아닙니다. 내부 코드에서도 시그니처 변경은 호출부 전부를 바꾸게 만듭니다.
그래서 시그니처는 처음부터 “확장될 자리(옵션/정책)”를 DTO로 확보하거나, 오버로드/빌더로 안정적인 확장을 설계하는 게 좋습니다.
✅ 핵심 요약
- ✔️ 메서드 시그니처는 이름 + 파라미터 목록으로 “호출 계약”을 결정한다(오버로딩의 기준).
- ✔️ 실무에서는 시그니처가 반환/예외/널 정책까지 포함한 “작은 API” 역할을 한다.
- ✔️ 좋은 시그니처는 호출 실수를 줄이고, 테스트/리팩터링/확장에 강하다.
- ✔️ 파라미터가 많아지면 DTO/VO로 의미를 만들고, 정책(예외/Optional)을 팀 규약으로 통일하자.