본문 바로가기

JAVA/Spring

스프링이란? 스프링의 기초 개념

 

1. 스프링은 프레임워크이다.

프레임이란 틀이고 워크는 동작한다는 뜻이다. 즉, 틀 안에서 동작을 한다는 것이다.

틀이 있으면 안에 구슬을 집어넣고 좌우로 움직이거나 위 아래로 움직여도 

구슬은 틀을 벗어날 수 없다. 프레임워크란 이 틀을 벗어나지 말라고 정해주는 것이다.

"개발자 마음대로 만들지 말고 틀을 제공할테니, 틀에 맞춰서 개발을 하라" 라는 뜻.

 

2. 스프링은 오픈 소스이다.

오픈소스라는건, 소스코드가 공개되어 있고, 내부를 고칠수도 있다는 것이다.

스프링이 어떻게 만들어져있는지 내부를 볼 수가 있고, 불편한 부분은 고쳐서 기여도 할 수 있다.

 

3. 스프링은 IOC 컨테이너를 가진다 (*스프링의 핵심이다)

IOC란 Inversion of controll의 약자이자, 제어의 역전이라는 뜻이다.

제어의 역전이란? 주도권이 스프링에게 있다는 것이다.

 

-클래스와 오브젝트

클래스(class)란 설계도이고,

오브젝트(object)는 실체화가 가능한 것이다.

클래스에는 일반클래스도 있지만 abstract class(추상 클래스)도 있다.

롤을 예로 들어서, 누누라는 클래스가 있다면 누누를 만들기 위한 클래스니까 누누를 만들기 위한 설계도이다.

누누는 실제로 게임을 할때 등장하기 때문에 실체화가 가능한 클래스이고, 이것이 오브젝트이다.

반면 롤에는 캐릭터라는 것이 있는데, 캐릭터란 굉장히 추상적인 의미이다.

캐릭터엔 누누도, 케이틀린도 올 수 있다. 캐릭터는 추상적인것이기 때문에 실체화가 불가능하다.

캐릭터 자체는 게임 속에 존재할 수 없는 것들이고 오브젝트가 아니다.

인스턴스(instance)란 실체화가 된 것이다.

누누가 전장의 협곡에서 돌아다니고 있으면 누누는 실제로 게임속에 존재하는, 실체화 된 것이다.

 

다른 예로, 가구란 실체화되지 않은 것이고 추상적인 것이다.

하지만 의자와 침대는 실체화된 것이고 이것을 오브젝트라고 부른다.

오브젝트로 존재하다가 세상에 튀어나온 순간 실체화가 되었기 때문에 인스턴스라고 부른다.

public void make() {
	의자 s = new 의자();
}

위와 같이 내가 오브젝트를 직접 new 해서 heap이라는 메모리 공간에 올리게 되면

의자의 주소는 reference 변수 s이고, s는 new를 만든 메소드 내부에서 관리하게 된다.

make() 함수에서 의자를 new하면 실체화시켜서 메모리에 띄운 것이고 주소는 s가 들고 있으며, 

s는 메소드가 실행되는 순간에만 메모리에 떠 있다.

public void use() {
	의자 s = new 의자();
}

make()함수의 의자와 use()함수의 의자는 서로 다른 의자이다. reference 변수의 주소는 각각의 메소드가 관리하는데,

이렇게 되면 나중에 의자를 공유하는 것이 힘들고 make()의 의자를 쓰기위해 넘겨받는 로직을 짜야한다.

이 때, 스프링이 IOC를 해준다.

클래스로 만든 수많은 오브젝트들을 스프링이 전부 스캔해서 자신이 직접 객체들을 띄우는 것이다.

스프링은 스캔하여 이것들을 읽어서 메모리에 올려주고, 이것이 IOC이며 주도권이 스프링에게 있다는 것이다.

 

4. 스프링은 DI를 지원한다.

DI란 Dependency injection(의존성 주기)

예전에는 내가 new를 해서 내가 주소를 관리했다면, 이젠 스프링이 스캔해서 오브젝트를 메모리에 띄우기 때문에

내가 아닌 스프링이 관리하는 것이고(제어의 역전)

스프링이 관리하는 이 객체를 내가 원하는 모든 곳, 모든 클래스의 메소드에 가져와서 사용할 수 있다.

스프링이 스캔을 하면 오브젝트는 딱 한번 메모리에 뜨고 그 오브젝트를 모든 곳에서 공유해서 사용할 수가 있다.

모든 곳에서 사용하는 의자는 모두 같은 의자이다. 이렇게 모든 곳에 가져와서 쓰는 것을 DI 라고 한다.

 

5. 스프링은 엄청나게 많은 필터를 가지고 있다.

A나라와 B나라가 전쟁중이고, B나라는 A나라에게 스파이를 보내서 몰래 진입한다.

문지기에게 A나라 사람이 아닌 B나라 사람이라면 걸러내라는 임무를 줄 수 있다.

그래서 A나라는 입구에서 ID카드로 어느 나라의 사람인지 확인을 한다.

이렇게 검열의 기능을 하는 부분을 필터라고 한다. (필터란 문지기 같은 것)

또한 왕궁을 방문하려면 권한이 필요한데, 해당 사람이 권한을 갖고 있는지 확인하고 걸러내는 

임무를 줄수도 있다. 이 또한 필터이다.

전자는 톰켓, 후자는 스프링 컨테이너라고 볼 수 있다.

 

톰켓과 스프링 컨테이너는 필터를 들고 있는데 톰캣의 필터는 실제로 필터라고 불리고,

필터에 기대는 파일을 web.xml이라고 한다. 

스프링 컨테이너가 들고있는 필터는 인터셉트라고 부른다. 누가 들어올 때 권한을 체크하고 허락한다.

모두 필터라고 생각하면 된다. 

 

6. 스프링은 엄청나게 많은 어노테이션을 가지고 있다. (리플렉션, 컴파일체킹)

어노테이션은 주석 + 힌트이다.

컴파일러가 무시하는 것을 주석이라고 한다.

어노테이션은 주석인데, 컴파일러가 무시하는게 아닌 뭔가를 체킹할 수 있도록 힌트를 주는 주석이다.

스프링은 어노테이션을 통해 주로 객체를 생성한다.

@Component

@Controller

@Autowired

이렇게 어노테이션을 직접 생성하고, 각각의 어노테이션이 어떤 역할을 하는지 미리 약속한다.

@Component 어노테이션이 붙어있는 클래스는 메모리에 로딩하라, @Autowired 어노테이션이 붙어있는

클래스는 로딩된 객체를 해당 변수에 집어넣어라 등의 약속을 할 수 있다.

어떤 클래스가 있을 때 개발자가 직접 new 하기보단 IOC를 사용하는 스프링에서는,

클래스 위에 @Component가 붙어있다면 스프링이 해당 클래스를 스캔해서 읽을때

위에서 약속했던대로 자신의 메모리 공간에 클래스를 로드하게 된다. 

스프링이 객체를 생성할 때 어노테이션 기법을 사용하는 것이다.

@Autowired //로딩된 객체를 해당된 변수에 집어넣어라
class B {
A a; //선언
}

 

메모리에 있는 A클래스를 B 클래스에서 사용하고 싶다면 위와 같이 사용한다.

 

나중에 스프링이 B 클래스를 스캔해서 읽어들일때, 클래스 안에 어떤 것이 있는지 분석하는 기법을

리플렉션이라고 한다. 런타임 순간에 발생하며 리플렉션을 통해 특정 클래스 내부의 메소드,필드,어노테이션을 체킹할 수 있다. 

 

7. 스프링은 MessageConverter를 가지고 있다. 기본값은 현재 Json이다.

영어권 사람과 한국 사람이 있다면, 서로 통신하여 메세지를 주고 받고 싶을때 보내는 사람이 번역해서 메세지를 보내거나 받는 사람이 메세지를 받아 번역해야하는 불편함이 있다.

따라서 한국사람도 영어권 사람도 이해할 수 있는 중간 언어를 만들어 문제를 해결한다. 

프로그래밍에서는 이러한 중간언어로 Json을 사용한다. (=json: 모든 나라의 사람들이 이해하기 쉬운 언어,

예전에는 xml을 사용했었다)

 

자바의 오브젝트와 파이썬의 오브젝트는 서로 생긴것이 달라서 오브젝트를 각자 전달하면 서로 힘들게 되는데,

따라서 자바 오브젝트를 중간에 json으로 변경해서 파이썬에 전달한다. 

자바 오브젝트가 전송되기 직전 중간데이터 json으로 바뀌고 전송되면 json이 파이썬으로 바뀌는 구조인 것이다. 

(자바 오브젝트를 파이썬으로 바꾸는건 어렵지만 json 오브젝트를 파이썬으로 바꾸는건 쉽다)

이렇게 오브젝트를 누군가에게 전송할 때 중간데이터인 json으로 Converte해주는 것이 MessageConverter이다.

-요청을 받아 자바를 파이썬으로 던질때 중간 데이터 json으로 바꿔주는 것이 MessageConverter

MessageConverter는 스프링의 라이브러리로 존재하며, 기본값은 현재 json이다.

응답을 받을 때도 MessageConverter가 동작해서 json 데이터를 자바나 파이썬으로 변경해준다.

 

8. 스프링은 BufferedReader와 BufferedWriter를 쉽게 사용할 수 있다.

데이터란 통신할 때 전기선으로 가게 되어있으며, 전기선을 통해 데이터가 전류로 이동을 하는데

이 때 bit단위로 통신이 된다(0,1,0,1,1 이런식으로 데이터를 보낸다)

이러한 bit 단위 통신은 이해하기 어렵기 때문에 영어와 같은 문자로 나타내고 싶어졌으며,

나타내기 위해서는 8bit가 필요했고 데이터를 보낼 때 8bit 씩 끊어 읽으면 한 문자씩 받을 수 있다고

알려줌으로써 이것이 통신의 단위, 1바이트가 되었다.

*영어권 국가를 기준으로 8bit=1Byte가 되었다. 한글은 8bit가 아닌 최소 16bit가 필요하다. 

한국을 기준으로 만들었다면 16bit가 1Byte 였을 것이다.

 

국가마다 사용하는 언어는 다르기 때문에, 전세계적으로 본다면 하나의 문자를 표현하기 위해 필요한 바이트는 나라마다 다르다. 예컨대 중국은 3바이트, 한국은 2바이트, 미국은 1바이트가 필요하다.

전세계적으로 커뮤니케이션을 하는 시대에 자기만의 방식으로 글을 인코딩하게 되면 데이터 통신하는 것이 불가능해지니까 이것을 유니코드에서 정리한 것이 UTF-8 이라는 캐릭터 인코딩이며, 3Byte 통신이다.

선으로 데이터를 보낼 때 통신은 ByteStream이라고 하고 이는 1Byte를 보낸다는 것이며

이렇게 전송하면 프로그램은 InputStream으로 읽는다. ByteStream은 문자가 아닌 바이트 통신을 하고 있으니까

이것을 문자로 변경하기 위한 InputStreamReader라는 클래스가 있다. (바이트를 문자로 바꿔주는 클래스)

InputStream은 배열로 여러 개의 문자를 받을 수 있는데, 배열의 단점이 크기가 정해져있는 것이라

크기를 작게 잡으면 문자를 전부 받을 수 없고 크기를 크게 잡으면 낭비를 하게 된다.

결국 가변길이의 문자를 받을 수 있는 BufferedReader로 데이터를 받게 되었다.

 

즉 BufferReader와 BufferedWrite는 통신의 ByteStream을 통해 데이터를 전송할 때 전송 단위가 문자열로 

가변길이 데이터를 쓰게 해주는 클래스이며, 데이터를 쓸때는 BufferedWriter를, 데이터를 받을 때는 BufferReader를 사용한다.  

이것은 스프링에서 @ResponseBody어노테이션을 사용하면 BufferedWriter가,

@RequestBody어노테이션을 사용하면 BufferedReader가 작동하기 때문에 직접 구현할 필요 없이 사용 가능하다.

 

 

 

 

 

해당 게시글은 '최주호' 님의 스프링부트 개념정리 강의를 참고하였습니다.

출처 https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8-%EA%B0%9C%EB%85%90%EC%A0%95%EB%A6%AC/dashboard

 

 

'JAVA > Spring' 카테고리의 다른 글

[스프링] 패키지 이름, UTF-8  (0) 2022.02.17
스프링 컨테이너  (0) 2022.01.08
스프링부트 JPA 개념잡기  (0) 2022.01.08
web.xml과 FrontController 패턴  (0) 2022.01.06
스프링부트의 동작 원리  (0) 2022.01.06