Spring Boot (+ RESTful)

Spring Boot - '프로젝트 구조 이해' / 어떤 원리와 어떤 관계, 어떤 순서로 실행이 되는 것인지 프로젝트 구조와 함께 확실하게 파악!

wy-family 2024. 12. 14. 13:33

h2 db 에 member 정보 2개 정도 입력을 해보고나서

Controller, Service, Repository, 3-tier 를 이용해서 data 를 서로 어떻게 연결하는지 확인해보자.

 

입력을 해주고 나서, Run Selected 를 눌러주자.

select * from member, member의 모든 것(*) 을 불러오는 것 까지 해봤다.

행 하나를 추가해보자.

실행을 할 때, 드래그해서 선택한 후에 run, 그래서 Run Selected 라는 것.


자, 이제 우리가 만들어야 하는 건,

FrontController, HandlerMapping, ViewResolver 는 framework에서 제공해주는 것이라서

우리는 Controller, Service, Repository 를 만들어서 연결해서 쓰는 것.

 

먼저 정리를 좀 해보자면,

Controller - HomeController

Service - HomeService 라는 interface가 하나 있고, impl 구현체가 하나가 있다

Repository - 는 JpaRepository 에서 제공해주는 interface를 상속받아가지고 HomeRepository 라는 interface를 만들어놓았다.

참고 - @Repository 어노테이션은 생략이 가능하다.
왜냐면 repository에 오는 건 거의 다 interface 만 오게 될 것이다. 다른 class 를 넣지 않는다.
그래서 일반적으로 repository 패키지 안에는 interface 들이 일반적으로 오기 때문에
자동으로 스캔을 해가지고 메모리에 올리게 되어 있기 때문임.

 

 

자, 이제 HomeController로 가보자.

클라이언트 요청을 받을 때 @GetMapping("/memberList")

view가 있는 형태로 갈려면, public String 으로 해줘야 한다. String 을 리턴 해줘야 하는데, 그 이유는?

 

public String을 사용하는 이유는 컨트롤러 메서드가 뷰(view)의 이름을 반환하기 때문입니다.


설명

  1. Spring MVC에서 @GetMapping과 같은 어노테이션은 클라이언트의 요청을 컨트롤러 메서드에 매핑합니다.
  2. 메서드 반환 타입이 public String이면, 이 반환값은 뷰의 이름으로 해석됩니다.
    • 뷰는 주로 HTML 파일이나 JSP 파일과 같은 화면 파일입니다.
    • Spring은 반환된 뷰 이름을 바탕으로 해당 뷰 파일을 찾아서 화면에 표시합니다.
  3. 따라서 public String을 사용하면 메서드의 반환값이 화면을 렌더링할 파일의 이름이 됩니다.

  1. 클라이언트가 /memberList로 요청을 보내면,
  2. showMemberList() 메서드가 실행되고,
  3. "memberList"라는 문자열이 반환됩니다.
  4. Spring은 이 반환값을 보고 memberList.html 또는 memberList.jsp와 같은 파일을 찾아 렌더링한 뒤 클라이언트에게 화면을 보여줍니다. (여기서는 JSP 가 아니고 Thymeleaf 로 할거니까 html)

핵심 포인트

  • 메서드의 반환 타입이 String이면 뷰의 이름을 반환합니다.
  • 반환된 뷰 이름에 따라 Spring이 적절한 뷰 파일을 찾아 클라이언트에게 화면을 렌더링합니다.

이와 같은 구조 덕분에 요청에 대한 결과를 화면(View)으로 반환할 수 있습니다.


이 때는 ViewResolver가 필요가 없다. view 가 들어갈 디렉토리는, templates에 들어갈 것.

 

이제 컨트롤러는 서비스한테 회원 전체 목록 요청을 해야 한다.

그러면 HomeService 를 손봐야 한다.

 

 

서비스 인터페이스를 이제 임플리멘테이션 했으니까 오버라이드를 해줘야 한다.

 

Impl 로 가보면, 마우스를 가져다가 가만히 있으면, 임플리먼트할 메서드를 선택하라고 뜬다.

 

지금 여기서 자동으로 return 을 List.of() 이라고 했다.

하지만 여기서는, repository 에 있는 메서드를 이용해서 DB 에서 회원 전체의 목록을 받아서 리턴을 해줘야 한다.

일단 repository를 손보기 전에, return null 로 바꿔주자.

 

Jpa에서 DB 의 Member 테이블에 있는 전체 목록을 가지고 오려면,

메서드를 만들어야 하는데, 만들 필요가 없다.

JpaRepository 에 전체 목록을 가지고 오는 메서드, findAll 이라는 메서드를 제공해주고 있다.

EntityManagerFactory 는 구현체인데, EntityManagerFactory 가 HomeRepository 라는 인터페이스를 자동으로 상속 받아가지고, 인터페이스 안에 있는 메서드를 구현을 한다.

그럼 findAll 은 무엇을 하냐면, SQL 을 뭔가 내부적으로 만들 것.

어레이 리스트 List<Member> 에다가 전체 회원 목록을 묶어가지고 return 을 해줄 것.

findAll 구현체를 우리가 직접 만드는 게 아니다. 이미 다 만들어져있다.

지금 HomeRepository 에 보면 아무것도 입력해놓은게 없지만, findAll을 쓰면 전체회원목록을 가지고 갈 수 있다는 것.

DB 쪽은 이해만 한다면, 간단하게 끝이 난다. extends JpaRepository 만, extends 로 상속받으면 끝이다. 구현체가 다 만들어지기 때문. 

 

이제 다시 service 로 가보자. service 는 repository가 필요하다.

HomeServiceImpl 서비스 클래스는 HomeRepository 객체가 필요해서, 

@Autowired 해서 Dependancy Injection (의존선 주입) 기법으로 메모리에 올라와 있는 HomeRepository 객체를 연결해가지고 사용을 하는 것.

그럼 이제 이 서비스는 누가 연동하는 것인가?

HomeController는 이제 service가 필요하다.

List<Member> member = homeService.memberList();

에서, 회원전체목록을 받아낸 member를 view 에서 뿌릴려면, 

객체 바인딩을 해야 한다. 객체를 연결해야 한다.

Model model 객체를 생성해가지고 모델에 연결시켜야 한다.

* Model 은 springboot framework의 ui 다.

"member", member - 연결할 객체 이름과 문자열.

 

지금까지 한 걸 한 번 정리를 하고 넘어가자.

 


 

객체 바인딩은 뭔가?

그리고 Autowired 는 뭔가?

간단하게 정리만 하고 넘어가자.

객체 바인딩이란?

  • 객체 바인딩은 클라이언트가 보낸 데이터를 객체에 자동으로 연결(바인딩) 하는 것을 의미합니다.
  • 주로 Form 데이터JSON 데이터를 자바 객체로 변환할 때 사용됩니다.

예시

public class Member {
    private String name;
    private int age;

    // getter, setter
}

@PostMapping("/addMember")
public String addMember(@ModelAttribute Member member) {
    // 클라이언트가 보낸 name과 age 값을 Member 객체에 바인딩
    System.out.println(member.getName());
    return "success";
}
  • 클라이언트가 name=John&age=25를 보내면 Member 객체에 자동으로 값이 바인딩됩니다.

@Autowired란?

  • @AutowiredSpring이 객체를 자동으로 주입(Dependency Injection) 해주는 어노테이션입니다.
  • 개발자가 객체를 수동으로 생성하지 않아도 Spring이 빈(Bean)을 찾아서 주입해줍니다.

예시

@Service
public class MemberService {
    public void printService() {
        System.out.println("MemberService 실행");
    }
}

@Controller
public class HomeController {

    @Autowired
    private MemberService memberService;

    @GetMapping("/test")
    public String test() {
        memberService.printService(); // 객체 주입 후 메서드 호출
        return "test";
    }
}
  • @Autowired를 사용하면 MemberService 객체가 자동으로 주입됩니다.
  • Spring이 해당 타입의 Bean을 찾아서 연결해 줍니다.

정리

  1. 객체 바인딩: 클라이언트의 데이터를 자바 객체에 자동으로 연결하는 것.
  2. @Autowired: 객체(Bean)를 자동으로 주입해주는 어노테이션.

 

 


이제, memberList.html 을 templates에다가 만들어야 한다.

 

그 전에,

이걸 update 로 바꿔줘야, 기존에 만들었던 게 날라가지가 않는다.

 

run 해보자.

일단, 연결이 된 걸 확인할 수 있다!

 

select 문이 실행이 된 걸 확인할 수 있다.

그런데 우리는 쿼리를 작성한 적이 없지만, findAll 이라는 메서드가 select 하고 연관이 되어 있다.

findAll() 하게 되면은 Hibernate 가 findAll 을 select 메서드로 generation 해서 처리해가지고 return 해주기 때문에,

findAll 이 호출되게 되면은, 내부적으로 저렇게 select 문이 만들어지는 것.

 

이제, html 에다가, 회원 목록을 실제로 뿌려주면 되겠다.

그건 다음 게시물로 넘어가도록 하겠다.