나는 인테리어 현장 관리자로도 일 해본적이 있다.
인테리어 시공현장은 공정대로 진행이 되는데 각 공정마다 전문가 혹은 기술자분들을 모셔서 작업을 진행한다. 예를 들어 목수분들이 틀을 잡을 때이다. 목수분들이 틀을 잡을때, 크게 보면 다 비슷해보인다. 그러나 중요한 것은 디테일이다. 몇 mm 차이로 문이 열리지 않는 경우도 보았기 때문이다. 나는 비록 인테리어 업계는 떠났지만 디테일하게 작업해주셨던 작업자 분들이 종종 떠오르곤 한다. 그만큼 실력 있으신 분은 기억에 남기 마련인 것 같다.
또한 나는 인테리어 현장에 있었던 경험을 통해 자신의 분야에 디테일을 아는 것이 곧 실력이다라는 것을 깨닫게 되었다.
프로그래밍 언어도 마찬가지! 대충 알지말고 디테일하게 알자!
프로그래밍 언어를 배우다보면 다양한 단어와 개념을 배우게된다. 다양한 단어와 개념을 어렴풋이 알고 쓰게 된다면, 후에 어떤 문제가 발생하면 어떤게 원인인지 찾아내기 힘들것이다. 그래서 어렴풋이 아는게 아니라 더욱 디테일하게 알아야한다. 그래야 디테일 갖춘 실력있는 개발자가 될 수 있는 것이다.
오늘은 static에 대해서!
프로젝트를 진행하면서 static 종종 보았다. 하지만 단 한번도 "왜 여기서 static을 쓰는거지?" 라고 생각해보지 못했다. 그냥 다들 그렇게 쓰는거니깐, 쓰나보다 싶었다.
But 이렇게하면 안된다. 디테일하게 알아야한다.
static의 사전적 의미가 뭘까?
"정적인" , "고정된" 이라는 의미를 가졌다.
클래스 프로그램 실행시 클래스 로딩이 되어 method Area에 생성된다. 이 때 클래스 내부의 static 키워드가 들어간 변수나 메소드가 초기화가 된다.
클래스로부터 객체를 만드는 과정은
클래스가 method Area에 생성 -> 생성자 -> new 연산자 -> heap 영역에 객체 생성
그러면 뭐가 고정적이라는 것일까?
인스턴스 변수는 heap 영역에 객체가 생성될때 생성된다.
그러나 static은 객체가 생성되지 않아도 method Area에 생성되어 있다.
즉, 인스턴스 변수에 비해 정적이라고 할 수 있는 것이다.
static은 언제 쓰일까??
클래스로부터 생성된 객체들은 클래스의 static 변수의 값을 공유할 수 있다.
즉,클래스로부터 생성된 객체들이 공통된 값을 가져야할 경우 static을 쓴다고 할 수 있다.
예를 들어 뭐가 있을까? 폰 번호를 만드는 클래스가 있다고 해보자.
한국에 있는 모바일 폰 번호는 옛날에 대부분 011으로 시작한다.(가정 ^^)

그런데 어느날 정책이 바뀌어 이제 모바일 폰 번호의 앞부분은 무조건 010으로 시작해야 된다고 한다. 어떻게 하면 될까? 공유되는 값이 static String preNumber만 바꾸면 되는 것이다.

static을 통해 각,객체들의 뒷번호는 동일하지만 앞번호만 공유되는 번호로 바꿀 수 있게 되었다.
Do you know that Static dosen't like OOP?
OOP를 아십니까?
OOP... 개발자 취업 준비를 하면 반드시 외우게 되는 단어이다.
Object-Oriented Programming
이름하여 객체지향 프로그래밍!
"객체" 중심으로 프로그래밍을 하는거야 라고 할 수 있다.
왜 객체지향하며 프로그래밍을 하는가?
OOP의 특성들과 원칙들을 따르는 핵심 이유는 코드의 재사용성,유지보수성,가독성을 높이는데 있기 때문이다.
그런데 static은 OOP적이지 않다고 한다! 왜 그럴까??
위에서 static을 알아봤으니 OOP를 알아보자.
객체지향 프로그래밍이 뭐지?
우리는 어떤 특성을 앎으로써 그 사물을 알 수 있다.
여기서 잠깐 퀴즈!
노란색이고 길고 껍질이 존재하고 속안에는 하얀색인 열대과일은??
정답은?!?!?

정답은 바나나이다!
방금 특성을 말하니 바나나를 유추 해내지 않았는가?
객체지향프로그래밍을 디테일하게 알기 위해서는 무엇을 해야할까?
객체지향프로그래밍의 4대 특성을 알아야하는 것이다.
4대 특성 그것은 바로 캡상추다
캡상추다(이것은 책-스프링 입문을 위한 자바객체 지향의 원리와 이해- 나옵니다 명서니 꼭 읽어보시길^^)
캡슐화와 은닉화 : 캡슐화는 객체의 속성과 메소드를 하나로 묶는 것이며, 객체 내부의 멤버를 외부에서 무분별하게 접근하지 못하도록 막는 것이 은닉화이다.

상상을 해보자. 내가 폰가게를 차렸다. 고객님이 원하시는 폰 번호를 받아서 phoneNumber1을 만들었다. 그런데 실수로 phoneNumber1.leftNumber에 잘못된 단어를 넣어버렸다.

결과는 어떻게 되었는가? phoneNumber1의 번호 자체가 엉망이 되어버린 것이다.
물론 극적인 예지만, 이렇게 다른 클래스에서 객체가 가진 데이터에 접근을 무분별하게 하는 것은 객체 자체가 가진 특성과 의미를 손상시킬 수 있는 것이다.
그래서 객체가 가진 데이터를 은닉화 하는 것이다.

leftNumber와 phoneNumber를 접근제어자 private를 써서 은닉화 시켰다. 위와 같은 상황이였다면 어떻게 될까?

빨간불이 들어온다. 즉, 객체의 은닉화된 데이터를 다른 클래스에서 접근하지 못하도록 하여 혹여나 발생할 사고를 줄일 수 있는 것이다.
객체의 데이터를 꼭 수정하거나 정보를 가져오고 싶다면?
수정할 때는 set메소드 만들어서 수정할 수 있다. 단, set메소드에 조건을 넣음으로써 객체의 특성에 맞게 객체가 가진 데이터를 수정할 수 있게 해주어야한다.
객체가 가진 정보를 가져올때는 get메소드 만들어서 쓰면 된다.
객체가 가진 데이터 접근시에 바로 접근하지 못하면 불편하다고 느낄 수 있지만, get메소드나 set메소드라는 인터페이스를 거치기 때문에 유지보수에 유리할 수 있는 것이다.


phoneNumber1.getLeftNumber() 의 값은 222-3333이다
어느날 갑자기 leftNumber가 아닌 lNumber로 이름을 변경해야 한다고 한다. 이럴 경우 어떻게 될까?


Phone 클래스에서 필드의 이름은 변경 되었지만, PhoneStore에서는 아무것도 바뀌지 않아도 되었다. 이렇게 클래스와 클래스 사이에 get메소드라는 인터페이스를 둠으로써 변경 사항에도 유연하게 대처할 수 있게 되는 것이다.
상속(확장) : 상위 클래스의 특징들을 하위 클래스들도 가질 수 있게 되는 것, 하위 클래스는 확장되는 것과 마찬가지인데 왜냐하면 상위 클래스 특징 + 하위 클래스의 특징들을 가질 수 있게 되기 때문이다.
추상화 : 객체로 만들고자 하는 것의 특징을 뽑아내는 행위
다형성 : 다양한 형태로 존재할 수 있다는 것! 오버라이딩과 오버로딩
객체지향 프로그래밍이란 위의 4대 특성에 맞는 프로그래밍이다.
다른 특성들은 내가 이해한대로 쉽게 정리하였다.
자, 왜 이렇게 캡슐화와 은닉화에 힘을 주었는지 눈치 챘을리라
static은 OOP 같지 않다고들 한다. 왜 그럴까?
왜? 바로 은닉화의 의도를 벗어나기 때문이다.
은닉화를 하는 이유는 객체가 가진 데이터에 무분별하게 접근하지 못하게 함으로써 객체의 특성을 지켜주는 것이다.
중요한 포인트는 객체가 가진 데이터에 무분별하게 접근하지 못하게 하는 것!
하지만 static 변수를 쓰게 되면 객체가 가진 데이터에 너무나도 쉽게 접근하여 데이터를 변형시킨다.

그것도 한 객체만 아닌 객체들 전부 데이터를 변형시켜 객체가 가진 특성을 완전히 변화시킨다.
그래서 static은 은닉화의 의도를 벗어나기 때문에 OOP같지 않다 말할 수 있는 것이다.
static이 안티패턴이 되는 이유
디자인패턴과 안티패턴을 알자!
디자인 패턴 : 업계에서 많이 사용하고 올바른 방법인 것. 올바른 방법이란 효율적이고 재활용성이 높은 방법
안티패턴 : 업계에서 많이 사용하지만 올바른 방법이 아닌 것. 비효율적이고 재활용성이 낮은 방법
왜 static은 안티패턴이며,비효율적이고 재활용성이 낮을까?
앞자리가 010으로 바뀌었지만 1번 고객은 자신은 역시 011를 써야한다며 바꿔주길 원한다. 이럴 경우가 당연히 있지 않겠는가?
어떻게 해줘야겠는가..? static은 공유변수인데,, 음,,, 일단은 바꿔볼까? 해서 바꿔보았다.

결과는? 하나도 안바뀌었다! 왜 그럴까?
static 변수가 바뀌어도 이전에 생성된 인스턴스에 영향을 미치지 못한다. 왜 그럴까? static은 고정된이란 뜻이다. 인스턴스 생성시 static 변수는 고정된 값으로 생성된 것이므로, 후에 static 변수를 바꾸더라도 바꾸기 전에 생성된 인스턴의 static 변수 값은 유지 되는 것이다. 즉, 생성된 인스턴스의 static변수의 값은 고정됨!
static 변수의 값을 바꾸었다면, 바뀐 후 생긴 인스턴스에게만 적용되는 것이다. 진짜일까?

static 변수를 바꾼 후 생성된 인스턴스에만 바뀐 값이 적용됨을 알 수 있다.
위와 같이 공통된 변수를 쓰면 되긴 하지만 만약에 바뀔 상황이 올 경우에는 이전에 생성된 객체에는 적용하지 못함을 알 수 있다. 이전에 생성된 객체를 재사용하지 못하는 아주 큰 불편함이 생기는 것이다.
그러면 어떻게 바꾸면 될까?
인스턴스 변수로 초기값을 설정해놓는 것이다.

이렇게 인스턴스 변수로 초기 값을 10으로 설정해놓고, 인스턴스 생성시 모두 010을 앞자리로 설정하되 특이한 요청시에만 setPreNumber로 앞자리를 바꾸어주도록 하는 것이다. 결과는?

phoneNumber1만 바뀐 것을 볼 수 있다.
클래스로부터 생성된 객체들이 모두 하나의 값을 같는다면 static을 써도 좋다. 그러나 이 경우는 굉장히 제한적이여야한다.
static은 진짜 변할 가능성이 없는 공유할만 변수에만 써야한다.
안티패턴이란 효율적이지 못한 재활용성이 낮은 패턴을 의미한다.
static으로 앞자리 번호를 공유하는 것과 인스턴스 변수의 초기값을 할당하는 것은 인스턴스 생성시 공유된 값을 갖게 된다는 면에서는 비슷해보인다.
그러나 추후 갑작스러운 변동에 따라 객체의 재사용성 또는 유지보수성에는 static을 쓰는 것보다 인스턴스 변수의 초기값을 할당하는 것이 효율적임을 알 수 있었다. 그렇기에 static은 안티패턴이라고 볼 수 있는 것이다.
그래서 static은 그냥 막 쓰는게 아닌 굉장히 고심해서 써야하는 것!
회고
이렇게나 static에 대해 깊이 공부할 줄 몰랐다. 이 글을 완성하게 된 것도 고민 고민 고민 고민 고민을 하며 왜 이런거지? 왜 안되지? 이건 왜 그런거지? 수많은 자료를 찾아보고 공부하며 글을 쓰게 되었다.
그러나 static 한 단어를 공부하는데 OOP특성을 제대로 공부하는 시간이 되었고, 내가 스스로 코드를 짜보면 static이 무엇이며 왜 조심해서 써야하는지를 몸으로 느낄 수 있었다.
혼자 공부할때는 가볍게 넘어갈 뻔 했지만, 멘토링을 받으며 공부를 하니 무엇이 중요한지를 확실하게 알 수 있고, 공부를 해보라는 이유가 있음을 깨달을 수 있었다. 대게 느린 걸음 같다. 부트캠프 할때 처럼 많은 양을 배워서 팍팍 진도가 나가서 뭔가를 만들어내는 쾌감은 없다.
아기 돼지 삼형제 이야기가 생각난다. 지푸라기로 지은 집, 나무로 지은 집, 오랜 시간이 걸려 벽돌로 지은 집 중에 늑대의 바람에 무너지지 않았던 집은 벽돌로 지은 집이였다.
글 초반에 말했던 디테일한 사람이 되기 위해서는 시간이 필요하다. 절대적으로 오랜 시간이 필요하다. 디테일을 가진 사람은 쉽게 무너지지 않는다. 마치 벽돌로 집을 것처럼 말이다.