자바답게 프로그래밍한다는 질문이 남긴 것

반응형

존경하던 분을 만난 다음 날까지 여러 질문이 머릿속에 남았다. 그중 가장 오래 붙잡힌 것은 “자바를 잘 사용하나요?”라는 물음이었다. 어느 정도 쓸 수 있는지 설명하려다 말이 길어졌고, 정작 무엇을 기준으로 잘한다고 말할지는 답하지 못했다.

그 질문을 다시 적어 보니 네 단계로 나뉘었다.

  1. 자바가 어떤 언어인지 알고 있는가?
  2. 자바를 사용한다는 것은 무엇인가?
  3. 자바를 잘 사용한다는 것은 무엇인가?
  4. 그렇다면 나는 어느 정도 사용하고 있는가?

문법과 프레임워크 이름을 나열해서는 마지막 질문까지 갈 수 없었다. 그래서 “자바답게”라는 말이 실제로 무엇을 뜻하는지 기본부터 다시 보게 됐다.

객체지향만 말하면 충분할까

당시에는 자바가 객체지향 언어이니 자바답게 쓴다는 것은 객체지향 설계를 잘하는 것이라고 먼저 해석했다. 캡슐화하고, 책임을 나누고, 구현보다 인터페이스에 의존하는 일이 분명 중요한 출발점이다.

하지만 지금은 객체지향이라는 한 단어만으로는 부족하다고 생각한다. Java는 클래스와 인터페이스뿐 아니라 함수형 인터페이스와 람다, record, sealed class, 패턴 매칭처럼 의도를 표현하는 여러 도구를 계속 추가해 왔다. 모든 문제를 상속 계층으로 만들거나, 반대로 모든 코드를 Stream으로 바꾸는 것이 자바다운 코드는 아니다.

언어 기능은 목적에 맞을 때 쓴다.

  • 상태와 불변식을 지켜야 하는 객체는 생성 규칙과 캡슐화가 드러나게 만든다.
  • 투명한 데이터 전달이 목적이면 record가 더 솔직할 수 있다.
  • 가능한 하위 타입을 제한해야 하면 sealed hierarchy가 의도를 표현한다.
  • 컬렉션 변환은 Stream이 읽기 좋을 때 사용하고, 복잡한 상태 전이는 평범한 반복문이 나을 수 있다.
  • checked·unchecked exception, 동시성, 컬렉션의 비용처럼 언어와 표준 라이브러리의 계약도 이해해야 한다.

결국 “객체지향 문법을 많이 썼다”가 아니라, 문제의 제약을 코드 구조로 얼마나 정확하게 표현했는가가 더 가까운 기준이었다.

POJO가 다시 보였던 이유

이 질문을 따라가다 Spring, EJB, POJO, AOP 같은 단어를 다시 읽었다. 예전에는 POJO를 단순히 “평범한 Java 객체” 정도로 외웠는데, Martin Fowler가 정리한 POJO의 배경은 특정 프레임워크의 무거운 컴포넌트 모델에 묶이지 않은 보통 객체에도 이름을 주자는 것이었다.

POJO라고 해서 자동으로 객체지향 설계가 좋아지는 것은 아니다. 반대로 프레임워크 annotation이 하나 있다고 무조건 나쁜 객체가 되는 것도 아니다. 중요한 질문은 업무 규칙이 특정 실행 환경, 저장 방식, 네트워크 제품 없이는 표현될 수 없는 구조인지다.

프레임워크는 유용하다. 다만 프레임워크가 문제를 대신 정의하게 두면 핵심 로직보다 설정과 annotation 이름이 먼저 보이기 쉽다. POJO를 공부하며 다시 본 것은 “프레임워크를 쓰지 말자”가 아니라, 프레임워크에 기대지 않고도 설명되는 규칙을 만들자는 방향이었다.

패턴과 제품을 혼동했던 장면

이 생각은 당시 우아콘에서 본 API Gateway 발표와도 이어졌다. API Gateway 제품을 사용했다고 해서 시스템의 API Gateway 패턴이 저절로 잘 설계되는 것은 아니다. 마찬가지로 POJO를 지원한다고 알려진 프레임워크를 쓴다고 해서 코드가 자동으로 단순하고 독립적인 객체 모델이 되지는 않는다.

도구 이름이 설계를 증명하지 않는다. 제품은 구현 수단이고, 패턴은 책임과 협력의 구조다. 당시 떠올렸던 발표는 API Gateway 패턴에는 API Gateway가 없다에 기록해 두었다. 객체지향 원칙을 변경 경계 관점에서 다시 본 내용은 SOLID 원칙과 변경 경계로 이어진다.

“잘 쓴다”를 확인하는 더 현실적인 질문

자바를 잘 쓰는지 단번에 판정할 수 있는 목록은 없지만, 코드를 볼 때 던질 질문은 조금 구체적으로 바뀌었다.

  • 타입과 이름만으로 유효한 상태와 불가능한 상태가 구분되는가?
  • 생성 직후부터 객체의 불변식이 지켜지는가?
  • 상속을 재사용 수단으로 남용하지 않고 실제 대체 가능성을 지키는가?
  • 표준 라이브러리에 이미 있는 계약을 다시 만들고 있지는 않은가?
  • null, 예외, 자원 해제와 동시성의 실패 경로가 보이는가?
  • 프레임워크를 걷어 내도 핵심 규칙을 읽고 테스트할 수 있는가?
  • 최신 문법을 사용한 이유가 간결함과 안전성으로 설명되는가?

이 질문들은 특정 스타일을 강요하기보다 선택의 이유를 확인하게 해 준다. 같은 요구사항이라도 작은 배치 프로그램, 장기 운영 서비스, 라이브러리의 답은 다를 수 있다.

지금의 생각

처음 질문을 받았을 때는 내가 아는 기술의 양을 설명하려 했다. 지금이라면 조금 다르게 답하고 싶다.

자바답게 프로그래밍한다는 것은 자바 문법을 화려하게 쓰는 일이 아니다. 언어와 표준 라이브러리의 계약을 이해하고, 문제의 목적과 제약이 코드에 자연스럽게 드러나도록 선택하는 일이다. 객체지향도, POJO도, 최신 언어 기능도 그 선택을 돕는 수단이다.

그리고 “잘 사용한다”는 답은 한 번 완성되는 것이 아니었다. 기본을 다시 읽고, 당연하게 쓴 코드를 설명해 보고, 설명할 수 없는 선택을 고치는 과정에 더 가까웠다. 그날 중언부언했던 답변 덕분에 적어도 무엇을 공부해야 하는지는 더 분명해졌다.

참고 자료

반응형
KEEP READING
카테고리 전체 보기 →

댓글