[스프링 입문] 2

smj_716·2025년 1월 7일

스프링 완전 정복

목록 보기
2/16

스프링 빈과 의존관계

1) DI (의존성 주입)

생성자에 @Autowired 가 있으면 스프링이 연관된 객체를 스프링 컨테이너에서 찾아서 넣어줌
즉, 외부에서 객체 의존 관계를 넣어주는 것

💡의존성 주입 3가지 방법

  1. 필드 주입
  2. setter 주입
  3. 생성자 주입

의존성을 변경할 일이 거의 없으므로 객체 생성 시 한 번만 주입하고 수정할 수 없는 생성자 주입이 안전하며, setter 주입은 객체를 수정할 가능성을 열어두어 위험할 수 있다.

2) 스프링 빈 등록방법

Bean(빈) : 스프링 프레임워크에서 관리되는 객체
IoC 컨테이너에 빈으로 등록이 되어야 의존성 주입 가능

👉 스프링은 스프링 컨테이너에 스프링 빈을 등록할 때, 기본으로 싱글톤으로 등록한다. (유일하게 하나만 등록해서 공유한다.) 따라서 같은 스프링 빈이면 모두 같은 인스턴스다.
설정으로 싱글톤이 아니게 설정할 수 있지만, 특별한 경우를 제외하면 대부분 싱글톤을 사용한다.

1. 컴포넌트 스캔과 자동 의존 관계 설정

@Component 애노테이션이 있으면 스프링 빈으로 자동 등록됨

‼️ @Controller, @Service, @Repository 는 @Component 을 포함

🖥️ MemberSerive

 @Service
 public class MemberService {
 
      private final MemberRepository memberRepository;
      
      @Autowired
      public MemberService(MemberRepository memberRepository){
          this.memberRepository = memberRepository;
     }
  • 생성자에 @Autowired를 사용하면 객체 생성 시점에 스프링 컨테이너에서 해당 스프링 빈을 찾아 주입함
  • 생성자가 1개 있으면 @Autowired 생략 가능

2. 자바 코드로 직접 등록

정형화 되지 않거나, 상황에 따라 구현 클래스를 변경해야 하면 설정을 통해 스프링 빈으로 등록해야한다.

ex : memberRepository라는 인터페이스가 있고, DB 또는 메모리에 데이터를 저장하는 두가지의 구현체가 있다고 가정하자. MemberService는 인터페이스에만 의존하고 구현체에는 의존하지 않는다. 즉, 메모리에서 DB 연결로 바꾸고 싶을 때 MemberService는 그대로 두고 SpringConfig에서 DB 구현체를 return해주기만 하면 되는 것이다.

🖥️ SpringConfig

@Configuration 
public class SpringConfig {

    @Bean
    public MemberService memberService() {
        return new MemberService(memberRepository());
    }
    
    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
 
  • @Configuration : 컨테이너임을 알려줌
  • @Bean : 빈 등록

회원 관리 예제 - 웹 MVC 개발

1) 홈 화면 추가

🖥️ HomeController

@Controller
public class HomeController {

    @GetMapping("/")
    public String home() {
        return "home";
    }
}
  • return 'home' -> home.html 파일로 접근함

2) 등록 기능

🖥️ MemberController

@Controller
public class MemberController {

    private final MemberService memberService;
    
    @Autowired
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
    
    @GetMapping(value = "/members/new")
    public String createForm() {
        return "members/createMemberForm";
    }
}

이후, 회원 등록 폼 HTML인 createMemberForm.html에서 회원이 이름을 작성하면, MemberForm 객체에서 그 데이터를 전달 받아 다시 컨트롤러로 전달해준다.

🖥️ MemberController

 @PostMapping(value = "/members/new")
 public String create(MemberForm form) {
    
    Member member = new Member();
    member.setName(form.getName());
    
    memberService.join(member);
    return "redirect:/";
}

전달 받은 Memberform 객체에서 getName()을 통해 회원이 등록한 이름을 얻어 새로운 member 객체에 저장함. 이 member 객체를 memberService에 전달하여 join하도록 한다.

  • redirect:/는 "/" URL로 이동하라는 의미
  • GET : 데이터를 URL에 포함하여 서버에 요청, 주로 데이터를 조회할 때 사용하며 URL이 노출됨
  • POST : 데이터 요청 본문(Body)에 담아 서버로 전송, 주로 데이터를 수정/삭제 할 때 사용하며 URL에 데이터가 노출되지 않음
    ("서버로 전송"은 클라이언트 html/브라우저 -> 서버 controller를 의미)

3) 조회 기능

🖥️ MemberController

@GetMapping(value = "/members")
public String list(Model model) {

    List<Member> members = memberService.findMembers();
    model.addAttribute("members", members);
    
    return "members/memberList";
 }
  • controller에서 Model에 데이터를 담아 뷰로 전달함
  • addAttribute("members", members)를 통해 members라는 키로 조회한 회원 리스트 데이터를 HTML로 전달함

🖥️ memberList.html

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div class="container">
    <div>
        <table>
            <thead>
            <tr>
                <th>#</th>
                <th>이름</th>
            </tr>
            </thead>
            <tbody>
            <tr th:each="member : ${members}">
                <td th:text="${member.id}"></td>
                <td th:text="${member.name}"></td>
            </tr>
            </tbody>
        </table>
    </div>
 </div> <!-- /container -->
 </body>
 </html>

0개의 댓글