내부 클래스

jaehun_dev·2023년 1월 15일
0

스프링

목록 보기
4/4
post-thumbnail

내부 클래스

클래스 내에 선언되는 클래스. 두 클래스가 서로 긴밀한 관계에 있을 때 주로 사용한다.

class Outer{
	...
	class Inner{
    	...
    }
    ...
}

내부 클래스의 장점

  • 내부 클래스에서 외부 클래스 멤버들에 쉽게 접근 가능하다.
  • 캡슐화를 통해 코드 복잡성을 줄일 수 있다.

내부 클래스의 종류

내부 클래스특징
인스턴트 클래스외부 클래스의 인스턴스 멤버처럼 다루어진다. 주로 외부 클래스의 인스턴스멤버 관련 작업에 사용된다.
스태틱 클래스외부 클래스의 static 멤버처럼 다루어진다. 주로 외부 클래스의 static 멤버, 특히 static 메소드에 사용된다.
지역 클래스외부 클래스의 메서드 또는 초기화블럭 안에서 선언되고 사용된다.
익명 클래스클래스의 선언 및 객체 생성을 동시에 하는 일회용 클래스.

인스턴트 클래스 vs 스태틱 클래스

내부 클래스 중 스태틱 클래스만이 static 멤버를 가질 수 있다.
final static 멤버는 상수이기 때문에 모든 종류의 내부 클래스에서 사용 가능하다.

인스턴스 클래스는 외부 클래스의 인스턴스멤버를 객체생성 없이 바로 사용 가능하다.
스태틱 클래스는 외부 클래스의 인스턴스멤버를 객체생성 없이 사용 불가능하다.

다른 클래스에서의 내부 클래스 접근

외부 클래스가 아닌 다른 클래스에서 내부 클래스를 생성하고 내부 클래스에 접근할 수도 있다. 그러나 이런 경우가 발생한다면 내부 클래스로 선언하면 안 되는 클래스를 내부 클래스로 선언했다는 것을 뜻한다.

Spring에서의 내부 클래스?

이 글을 쓰게 된 주 원인이 다음 코드다.

"hello-api"라는 get 요청에 대해 hello 객체를 response로 리턴해주고 있다. (이는 Jackson 등의 라이브러리를 통해 json 형태로 클라이언트에게 전송된다.)
Controller의 내부 클래스로 작성된 Hello 클래스는 static 클래스다. 나는 여기서 3가지 의문이 들었다.

  • 내부에 static 멤버도 없는데 왜 Hello 클래스는 인스턴스가 아닌 스태틱 내부 클래스로 작성되었는가? 실제로 static 키워드를 지우고 실행해도 아무 문제가 없었다.
  • static 내부 클래스인데, 왜 Hello 객체 생성 없이 Hello.setName()을 한다면 오류가 발생할까?
  • 기껏 Hello 클래스를 static으로 선언하였으면서, helloApi 메소드에서는 왜 hello라는 객체를 만드는 것일까?

공부 결과 그 답은 다음과 같았다.

1번 질문에 대한 답변

  • 내부 클래스에서 외부 클래스의 인스턴스를 쓰지 않는다면, 내부 클래스는 static으로 만드는 것이 좋다. 예시 코드에서 내부 클래스 Hello는 외부 클래스 HelloController의 멤버를 전혀 쓰지 않고 있다. 이럴 때 내부 클래스를 static으로 만드는 것이 좋은 이유는, '메모리 누수' 때문이다.
  • 메모리 누수에 대해서, static 내부 클래스는 '자신의 인스턴스'와 '자신의 기본 생성자'에 대한 정보만을 가지지만, 인스턴스 내부 클래스는 '바깥 클래스 참조'까지 가지게 되며, '바깥 클래스 참조'가 메모리 누수의 원인이 된다.
  • 인스턴스 내부 클래스는, 외부 클래스가 더 이상 사용되지 않더라도 그에 대한 참조가 존재하기 때문에 GC가 수행될 수 없다. 이에 따라 메모리 누수가 발생하며, 따라서 외부 클래스의 멤버를 사용하지 않는 내부 클래스의 경우 인스턴스가 아닌 static으로 선언하는 것이 바람직하다.
  • 결론: 내부 클래스가 바깥 클래스와 독립적으로 작동한다면 내부 클래스를 static으로 정의하자.

2번 질문에 대한 답변
Hello 클래스는 static이지만, setName 메소드는 static이 아니다. 따라서 Hello 클래스의 인스턴스 객체가 요구된다. 만약 setName 메소드 역시 static이라면

Hello.setName(name);

과 같이 사용이 가능할 것이다.

3번 질문에 대한 답변
controller에서는 결국 mapping으로 받은 request에 대한 response를 리턴해주어야 한다. 그 리턴을 객체로 하기 위해서는 결국 클래스의 객체 생성은 필수적이다.

profile
취업준비생/코딩&프로젝트 같이 하실분 연락주세요

0개의 댓글