어느새 졸업프로젝트 스타트가 기말 시연 발표만을 앞두고 있다 🫢

기획도 어느 정도 끝나고, 간단한 AI 기술 검증도 한 후,

중간발표도 마쳤고, SW 중심대학 생성형 AI 공모전도 나가서 우수상도 탔다.

 

기말 발표 때는 아래 기능 구현을 중점으로 시연하기로 했다.

  1. DB(MySQL)에 사용자 기본 정보 저장 후 gpt로 전달
  2. gpt를 이용한 대화 후 추출한 키워드 저장하여 DB로 전달
  3. 졸음 감지 (하품, 목소리 피치 및 속도) + “졸려, 피곤해” 감지

AI 기술 구현이 주이지만

사용자 DB에서 정보를 전달하고, 대화 결과 키워드를 업데이트 하는 기능이 구현되어야 하기 때문에

간단한 백엔드 구현도 같이 하기로 했다.

 

UMC 워크북 때 프로젝트 기록을 많이 못했어서 졸프 프로젝트 기록만큼은.. 열심히 해봐야지 !!

 


프로젝트 기본 환경

- JAVA 17

- SpringBoot 3.3.5

- MySQL

- IntelliJ

- Mac

 

 

프로젝트 생성

https://start.spring.io

Lombok, Security, JPA, MySQL, SpringWeb 등의 의존성을 추가했다.

Generate를 한 후에 압축을 풀어준다.

IntelliJ 접속 후 open을 통해 spring initializer로 생성한 프로젝트를 찾아

아래 사진처럼 build.gradle을 클릭 후 open을 해주면 끝 !

 

 

문제가 없는 지 테스트 실행을 해볼건데,

처음엔 안된다 !

mysql과 연결 접속 정보가 필요한데 아직 그걸 적어주지 않아서 그렇기 때문에 

'build.gradle'에서 jpa, security, mysql은 주석처리 해준 후 실행을 해준다.

 

 

정상 실행됨 !

일반적으로 8080포트번호를 쓰기 때문에 

http://localhost:8080로 접속해보면

 

마지막으로 git에 연동하기 전에 gitignore 설정을 해준다.

https://www.toptal.com/developers/gitignore#:~:text=gitignore,-.io

 

gitignore.io

Create useful .gitignore files for your project

www.toptal.com

 

위 사이트에서 사용 언어와 개발환경 등을 입력하면 ignore 파일을 작성해준다.

복사해서 프로젝트 gitignore에 붙여넣기 하고 커밋하면 초기 프로젝트 생성 완료!

 

 

 

'SpringBoot' 카테고리의 다른 글

서블릿 vs. Spring MVC 비교  (0) 2025.04.07
AOP(Aspect-Oriented Programming)  (0) 2025.04.07
[SpringBoot] 자동 삭제 기능 구현 Scheduled Job  (0) 2025.01.21
[SpringBoot] API & Paging  (0) 2024.11.22
Spring IoC 컨테이너  (1) 2024.10.10

IoC 컨테이너

- IoC(Inversion of Control) 컨테이너는 객체의 생성 및 관리를 애플리케이션 코드가 아닌 프레임워크가 담당하도록 하는 디자인 패턴이다.

- Spring 프레임워크는 이러한 IoC 개념을 핵심으로 하고 있으며, 스프링 IoC 컨테이너는 애플리케이션에 필요한 객체(빈)를 생성하고, 객체 간의 의존 관계를 설정하고 관리하는 역할을 한다.

- 일반적으로 애플리케이션의 객체는 필요할 때 개발자가 직접 생성하고 연결하는 방식으로 개발되지만, IoC 패턴을 사용하면 프레임워크가 대신 그 역할을 수행해준다.

 


 

IoC 컨테이너의 역할

  • 빈의 생성 및 관리 : IoC 컨테이너는 애플리케이션 실행 시 빈을 생성하고 라이프사이클을 관리한다.
  • 의존성 주입 : 필요한 의존성(다른 빈) 을 객체에 주입해 준다.
  • 빈의 라이프사이클 관리 : 빈의 생성, 초기화, 소멸 등을 관리한다. 이를 위해 @PostConstruct, @PreDestroy 같은 라이프사이클 어노테이션을 사용한다.

 

 


IoC 컨테이너의 작동 방식

1. 객체를 class로 정의한다.

2. 객체들 간의 연관성을 지정한다

  • Spring 설정 파일(Config) 또는 어노테이션을 통해 객체들이 어떻게 연결될지(의존성 주입) 지정해준다.

3. IoC 컨테이너가 이 정보를 바탕으로 객체들을 생성하고 필요한 곳에 주입한다.

 

이 과정을 거쳐서 IoC 컨테이너는  POJO 기반의 개발을 가능하게 해준다.

POJO(Plain Old Java Object)는 복잡한 라이브러리나 프레임워크에 의존하지 않고, 순수한 자바 객체를 의미한다.

Spring은 POJO 기반의 개발을 지향하며, 즉 프레임워크에 종속적이지 않고 일반적인 자바 객체를 사용하여 비즈니스 로직을 구현할 수 있음을 뜻한다.

// UserService: POJO class
public class UserService {
	private UserRepository userRepository;
    
    // 의존성 주입 : 생성자
    public UserService(UserRepository userRepository) {
    	this.userRepository = userRepository;
    }
    
    public User findUserById(Long id){
    	return userRepository.findById(id);
    }
}

 

위 코드의 UserService는 어느 특정한 프레임워크나 라이브러리에 의존하지 않는 순수한 POJO이다.

Spring IoC 컨테이너가 UserRepository 객체를 자동으로 주입한다.

 


IoC의 핵심 개념

1. 의존성 주입 (DI : Dependency Injection)

- 객체 간의 의존 관계를 코드 내부에서 명시적으로 설정하지 않고, IoC 컨테이너가 필요한 의존성을 객체에 주입하는 방식

- Spring 컨테이너는 빈을 생성할 때, 이러한 종속성을 주입한다.

- 각 클래스 간 의존관계를 빈 설정(Bean Definition) 정보를 바탕으로 컨테이너가 자동으로 연결해준다.

- DI 원칙을 사용하면 코드가 더 깔끔해지고, 객체에 종속성이 제공되면서 분리가 더 효과적이다.

- 클래스를 테스트하기 더 쉬워지고, 종속성이 인터페이스나 추상 기본 클래스에 있는 경우 단위 테스트에서 스텁이나 모의 구현을 할 수 있다.

 

 

주입 방식

(1) 생성자 주입

- 생성자 기반 DI는 컨테이너가 종속성을 나타내는 여러 인수로 생성자를 호출하여 객체를 생성한다.

- 생성자는 객체가 생성될 때 필수적인 의존성(필드값)들을 보장하기 때문에, 의존성이 없는 객체를 만들 수 없음

- 객체가 생성될 때 필요한 의존성을 모조리 설정해버린다.

-> 객체의 불변성(Immunability)를 보장해준다.

public class A {
	private final B b;
    
    // 생성자를 통해 B가 주입됨
    public A(B b) {
    	this.b = b;
    }
}

 

(2) 세터 주입

- Setter 주입 방식은 런타임에 의존성을 주입함, 그렇기 때문에 의존성이 없더라고 객체가 생성될 수 있다.

- 선택적으로 의존성 주입이 가능하지만, 필수적인 의존성이 주입되어야만 할 때 이를 강제할 수 없음 - 치명적 단점

 

1. 주입 받으려는 빈의 생성자를 호출하여 빈을 찾거나, 빈 팩토리에 등록

2. 생성자 인자에 사용하는 빈을 찾거나, 생성

3. Setter의 인자로 주입

public class A {
	private B b;
    
    @Autowired
    public void setB(B b) {
    	this.b = b;
    }
}

 

 

(3) 필드 주입

- 필드 주입 방식 역시 세터 주입과 마찬가지로 런타임에 의존성을 주입

- 코드가 깔끔하고 단순하지만, 필드에 직접 주입되기 때문에 테스트 중에 의존성을 주입하는 것이 어려움

- 명시적으로 드러나는 의존성이 없기 때문에, 의존성 구조를 이해하기 어려워짐

- 의존성 관계가 드러나지 않기 때문에 Spring 컨테이너를 헷갈리게 해서 Bean들 간의 순환 참조 문제가 생길 수 있다.

public class A {
    @Autowired
    private B b;
}

 

 

2. 빈(Bean)

- Spring 컨테이너가 관리하는 자바의 객체

- ApplicationContext.getBean() 함수를 호출했을 때 얻어질 수 있는 것이 Spring의 빈이다.

- Spring은 빈을 통해 객체를 인스턴스화한 후, 객체 간의 의존 관계를 관리한다.

 

[ Bean으로 등록하여 관리하는 방식 ] 

1. @Component -> @Autowired : 묵시적 빈 정의

- 클래스에 @Component 어노테이션을 붙여주면, Spring은 자동으로 해당 클래스를 Bean으로 등록하며, 이를 사용할 수 있다. 따라서, 다른 클래스에서는 해당 클래스를 @Autowired 어노테이션을 통해 주입 받아 사용할 수 있다.

 

2. @Configuration -> @Bean : 명시적 빈 정의

- Spring 설정 파일에 Configuration 어노테이션을 추가하고, Bean 어노테이션을 붙여 명시적으로 빈을 지정

 

 

3. 서블릿(Servlet)

Spring Servlet은 스프링 프레임워크에서 제공하는 DispatcherServlet을 중심으로 동작하는 구조를 의미한다.

Spring MVC에서 DispatcherServlet은 Front Controller 역할을 하며, HTTP 요청을 받아서 적절한 컨트롤러로 전달하고, 응답을 처리하는 중요한 서블릿이다.

 

서블릿이란 ?

클라이언트의 HTTP 요청을 처리하고 그에 대한 응답을 생성하는 역할을 한다.

웹 서버는 요청을 WAS에게 넘기고, WAS는 요청에 따른 Servlet을 실행한다.

Servlet은 요청에 대한 응답을 클라이언트에게 보낸다.

1. 요청을 받은 Servlet Container는 HttpServletRequest, HttpServletResponse 객체 생성

2. web.xml을 기반으로 사용자가 요청한 URL이 어느 Servlet에 대한 요청인 지 찾음

3. 해당 Servlet에서 service() 메소드를 호출한 후, 클라이언트의 GET, POST 여부에 따라 doGet(), doPost() 호출

4. doGet(), doPost() 메소드는 동적 페이지를 생성한 후, HttpServletResponse 객체에 응답을 보냄

5. 응답이 끝나면 HttpServletRequest, HttpServletResponse 객체 소멸

 

 

서블릿 컨테이너란 ?

서블릿을 관리해주는 역할

Servlet이 어떤 역할을 수행하는 메뉴얼이라면, Servlet Container는 해당 메뉴얼을 보고 직접 핸들링하는 역할이다.

서블릿 컨테이너는 클라이언트의 요청을 받아주고 응답을 보낼 수 있게, 웹 서버와 Socket으로 통신한다.

Servlet 컨테이너는 이런 기능을 API로 제공하여 간편화했고, 우리는 서블릿에 구현해야 할 비즈니스 로직에 대해서만 집중할 수 있음

 

 

DispatcherServlet

스프링에서 가장 중요한 서블렛이다.

Front Controller 패턴을 구현한 서블릿으로, 모든 HTTP 요청을 중앙에서 처리하는 역할을 한다.

이후, 요청을 적절한 Controller로 전달하고, 로직을 실행한 후 응답을 생성해준다.

 

역할

  • 요청 수신 및 라우팅 : 클라이언트의 모든 요청을 받아서, 어떤 컨트롤러가 해당 요청을 처리해야 하는 지 결정
  • 컨트롤러와 상호작용 : 각 요청에 맞는 컨트롤러를 호출하고, 그 컨트롤러에서 처리된 결과를 바탕으로 뷰를 반환
  • 핸들러 매핑(Handler Mapping) : 핸들러 매핑을 통해 특정 요청 URL에 해당하는 컨트롤러를 찾아 호출
  • 뷰 리졸버(View Resolver) : 컨트롤러가 반환한 논리적인 뷰 이름을 실제 물리적인 뷰 파일로 변환해 클라이언트에게 응답

동작 과정

1. HTTP 요청 수신 : 클라이언트가 웹 서버로 HTTP 요청을 보냄 ->  이 요청은 서블릿 컨테이너에 의해 처리되고 서블릿 컨테이너는 이 요청을 DispatcherServlet에 전달

2. 핸들러 매핑 : DispatcherServlet은 요청 URL에 매핑된 적절한 컨트롤러 메서드를 결정

3. 핸들러 호출 :  매핑된 컨트롤러 메소드가 실행되고, 비즈니스 로직을 처리한 후 결과를 반환

4. 뷰 리졸버 :  컨트롤러가 처리 결과와 함께 반환한 논리적인 뷰 이름을 실제 뷰로 변환

5. 응답 반환 : 변환된 뷰를 기반으로 최종적으로 HTML, JSON, XML 등의 형식으로 클라이언트에게 응답 반환

+ Recent posts