본문 바로가기
IT 공부/공부하며 알게된 사실들

자바의 문법보다 더 중요했던 소프트웨어 개발 원리에 대한 이해

by exdus3156 2023. 11. 24.

자바를 학원에서 처음 맛 봤을 때는 정말 쉽게 배웠다. 클래스를 기초 빌딩 블록으로 사용하는 C#이나 C++도 문법적 기능은 쉽게 공부했다.

하지만 왜 나는 자바를 학원에서 배웠음에도 전혀 소프트웨어를 개발하지 못했던 것일까?

학원에서는 단순히 자바의 기초 문법과 스프링 포맷만 가르치고는 바로 프로젝트 개발로 뛰어들었다.

나는 그 방식에 전혀 적응하질 못했다.

분명히 자바 강의와 책을 통해 사용법을 익한 상태였다. 하지만 사용법은 알고 있었지만 사용할 줄을 몰랐다.

아무리 문법을 알아도 기껏 사용할 수 있는 것이라곤 전형적인 C언어 스타일로 간단한 알고리즘과 자료구조 문제를 푸는 방식 뿐이었다.

게다가 애초에 소프트웨어를 만들라고 과제를 던져주는데, 나는 정작 소프트웨어 개발 자체가 무슨 의미이며 어떤 프로세스를 거치며, 왜 그런지 전혀 이해하질 못했다.

소프트웨어 개발 자체가 너무 거대하고 추상적으로 다가왔던 것이다.

 

학원도 그랬지만 다른 강의나 책들도 다 마찬가지였다. 일단 일련의 문법 및 프레임워크 사용법을 익히면 개발자가 알아서 뚝딱 소프트웨어를 만들 수 있다고 가정하는 것 같았다.

하지만 현실 세계의 소프트웨어는 단순히 도구 사용법을 달달 숙달한다고 해서 할 수 있는 것이 아니었다.

무언가 내가 이해할 수 없는, 프로그래밍 언어 문법과 소프트웨어 개발 사이에 큰 공백이 있는 느낌이었다.

하지만 대부분의 조언들은 "프로그래밍을 매일 꾸준히 하세요" 수준의 조언에 그쳤다. 

그러나 나는 밀도 있게 배우고 싶었다. 경험을 쌓아 직관적으로 저 공백을 메울 수 있을까? 의문이 들었기 때문이다.

이 공백을 메우고 싶은 욕구 때문에 나는 개발 공부가 어려우면서도 결코 포기하질 않았다

무작정 헤딩만 했던 것 같다. 이런 저런 책들을 읽고, 솔직히 이해하지도 못하면서도 단지 유명 대학의 소프트웨어 공학에서 교과서로 사용한다는 이유로 책을 잔뜩 사기도 했다. 책 제목과 유명세에 낚이기도(?) 했던 것 같다.

대부분 읽다가 지치고, 또 다시 읽고 즐거워하다가 지치고의 반복이었다. 부끄럽지만 아직 빳빳한 새 책도 있다..;

 

이렇게 공부하는 과정에서 알듯 말듯한 느낌이 재밌으면서도 싫었다. 하나를 알면 열 개의 가려운 곳이 생겼다. 이 개념을 익히면 가려운 곳을 긁어줘서 좋았지만 어차피 다른 가려운 곳이 열 개가 생기니까..

지금 와서야 알게 된 것이지만, 소프트웨어 개발 자체가 사고력의 기예에 가까운 작업이다. 그래서 소프트웨어 개발론에 대한 대부분의 설명들이 매우 추상적이고 관념적인 경우가 많다.

그래서 공부를 하면 오히려 가려운 곳이 자꾸만 생기는 것 같다. 

 

그런데 조금씩 조금씩 실마리가 하나씩 풀어지는 느낌을 최근에 받고 있다.

<객체지향의 사실과 오해>라는 책과 <코드 컴플리트>에서 읽은 것들이 뭔가 앞 뒤가 맞아 떨어지는 기분을 받는다.

더 재밌는 것은 자바의 객체지향 문법 키워드들을 바라보면 이제는 문법 뒤에 숨은 설계 문맥들이 읽혀진다는 점이다.

물론 취준생으로서 나는 자바의 모든 문맥을 알지 못한다.

하지만 예를 들어, 자바 기초 교과서에 Student 라는 객체를 예시로 들면 나도 모르게 머릿속에서, "아, 객체지향 설계에서 도메인 모델링을 통해 학생이라는 개념을 포착하고 해당 개념에게 무언가 책임을 할당하고 있구나!"라는 상상이 된다.

자바 인터페이스 문법을 보면, "아, 이 인터페이스를 사용하는 모듈은 상위 컴포넌트로서 제어 흐름과 코드 의존성을 역전시키기 위해 인터페이스를 사용하는구나", 혹은 "이 인터페이스를 통해 이 모듈은 이런 식으로 메시지를 호출하는구나!", "이 인터페이스는 적절하게 추상화된 것일까? 아니면 너무 지나치게 추상화되어 메시지 수신 객체에게 너무 많은 책임을 할당하고 있는 것일까?", "혹시 인터페이스에 캡슐화를 위반하는 정보가 누수되고 있지는 않을까?", 등등.... 이런 상상이 펼쳐지는 것이다.

상속 문법이 나오면 예전에는 그저 관념적으로, "그래 Dog는 Animal의 한 종류지.." 이런 수준에서 상상하고 그쳤다면, 지금은 "Animal의 공통 인터페이스가 어떤 모듈에서 사용되고 있구나.", "Dog는 해당 공통 인터페이스의 역할을 같은 추상 레벨에서 다뤄야 하는 거구나.", "만약 Dog가 Animal의 공통 인터페이스를 이상한 방식으로 수행해서 호출하는 모듈이 Dog라는 서브클래스에 따라 다른 처리를 수행하게 만든다면 LSP를 위반한 것이겠지..." 라는 상상에 빠진다.

private, public 접근 제어자를 보면 단순히 접근을 막는 수준을 넘어서서, "private으로 막았다 한들, 혹시 이 예제에서 내부 구현에 대한 정보가 누수되고 있지는 않나?", "이 객체가 정말 상속이 될까? 만약 상속 된다면 혹시나 private으로 막은 제어자를 protected로 바꿀 필요가 있을까? 아니라면 final로 막아야 할까? 왜 교과서에는 상속에 대비해 상속을 막는 키워드는 중요하게 다루지 않는걸까?" 와 같은 상상이 생긴다.

메소드에서 객체를 넘기는 예제를 보면, 혹시나 코드 내부에서 그 객체의 상태를 이리저리 변경시킨다거나 하는 행동을 하고 있지는 않은지 관심이 간다. 

예전에는 "멤버 변수는 private으로 막아라!" 라는 조언을 그저 따르기만 했다. 이유를 몰랐다. 알고 싶어도 어디에도 적혀 있지 않았다. 그러나 이제는 약간이나마 문맥이 상상이 된다. 반대로도 상상하기도 한다. 혹시나 public으로 열어 줄 여지가 있지는 않은지 말이다. 단순히 값을 전달하고 말아버리는 박스 개념에 불과하다면 구조체로서 전달해도 되지 않을까? 이런 상상을 하곤 했다.

 

예전에는 보이지 않았던 것들이 하나 둘 보인다.

최근에 느낀 점 하나는, 자바와 같은 OOP 언어가 정말 소프트웨어 설계 기법과 절대 땔 수 없는 관계라는 사실이다.

자바든 C#이든 자바스크립든, 개발자가 사용하는 프로그래밍 언어는 컴퓨터에 가까운 명령어가 아니라 인간이 이해하는 언어라는 말이 있다. 고급 언어나 저급 언어라도 불린다.

이 말의 의미가 프로그래밍 언어가 단순히 사람이 읽기 쉽다는 뜻이 아닌 것 같다.

그 보다는 소프트웨어 개발에 있어 필요한 원칙, 원리들을 문법 키워드로 포착해서 그러한 원칙과 사고력을 표현하는 언어라는 뜻이 아닐까 싶다.

코드를 읽는다는 것이 단순히 코드가 하려는 알고리즘을 이해하는 수준을 넘어서야 할 것 같다.

문법 키워드의 사용에 대해 하나하나 이유를 들어 설명할 수 있다면, 그래서 그 코드를 만든 개발자와 개발 팀이 무슨 생각을 하고 있었는지 파악할 수 있다면 정말 기분이 좋을 것 같다.

프로그래밍 언어는 상징화된 문법 키워드 내부로 설계 원칙과 개발팀이 고려하는 원칙들을 문맥으로 숨긴다. 주석이라는 도구도 있지만 말로 표현하는 데는 한계가 있는 법이다.

이렇게 문법의 기능만 받아들이는 것이 아니라, 코드라는 전체 문맥을 고려해서 문법 키워드 뒤에 숨은 개발팀의 사고의 기예를 함께 느낄 수 있다면 정말 좋을 것 같다.