소프트웨어 설계에서 꼭 알아야 할 원칙 중 하나인 CQS는 "명령과 조회를 분리하라"는 개념이다.
이 원칙을 따르면 코드의 명확성, 유지보수성, 테스트 용이성이 향상된다.
이번 포스트에서는 CQS의 개념과 적용 방법, 장단점을 예제와 함께 정리해보자.
CQS는 Command Query Separation의 줄임말로, "하나의 메서드는 상태를 변경하거나, 상태를 반환하거나 둘 중 하나만 해야 한다"는 원칙이다.
상태를 변경하면서 동시에 값을 반환하는 메서드는 CQS 위반이다.
이 원칙은 객체의 명령(변경)과 질의(조회)의 책임을 명확히 분리함으로써 코드의 명확성을 높인다.
void
메서드 형태로 구성된다.// Command
public class AddUserCommand {
private String username;
private String password;
public AddUserCommand(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() { return username; }
public String getPassword() { return password; }
}
// Command Handler
public class UserCommandHandler {
public void handleAddUserCommand(AddUserCommand command) {
// 실제로는 DB 저장 로직 등이 들어감
System.out.println("User added: " + command.getUsername());
}
}
// 실행
UserCommandHandler handler = new UserCommandHandler();
handler.handleAddUserCommand(new AddUserCommand("john123", "password"));
// Query
public class GetUserQuery {
private String username;
public GetUserQuery(String username) {
this.username = username;
}
public String getUsername() { return username; }
}
// Query Handler
public class UserQueryHandler {
public String handleGetUserQuery(GetUserQuery query) {
String userDetails = "User details for username: " + query.getUsername();
System.out.println(userDetails);
return userDetails;
}
}
// 실행
UserQueryHandler handler = new UserQueryHandler();
String result = handler.handleGetUserQuery(new GetUserQuery("john123"));
System.out.println(result);
CQS는 처음엔 조금 과해 보일 수 있지만, 프로젝트가 커질수록 그 가치가 드러난다.
특히 객체 설계를 명확히 하고, 테스트 가능성을 높이고 싶은 개발자에게는 꼭 고려해야 할 설계 원칙이다.
“읽기와 쓰기를 명확히 나누는 것, 그 단순한 원칙이 코드 전체의 복잡도를 줄여준다.”