Home > Backend > Spring > ๐Ÿƒ[Spring] ์˜์กด์„ฑ ์ฃผ์ž…(Dependency Injection)์„ ํ†ตํ•œ ๋Š์Šจํ•œ ๊ฒฐํ•ฉ(Loose Coupling) ์œ ์ง€.

๐Ÿƒ[Spring] ์˜์กด์„ฑ ์ฃผ์ž…(Dependency Injection)์„ ํ†ตํ•œ ๋Š์Šจํ•œ ๊ฒฐํ•ฉ(Loose Coupling) ์œ ์ง€.
Spring Framework

๐Ÿƒ[Spring] ์˜์กด์„ฑ ์ฃผ์ž…(Dependency Injection)์„ ํ†ตํ•œ ๋Š์Šจํ•œ ๊ฒฐํ•ฉ(Loose Coupling) ์œ ์ง€.

  • ์•„๋ž˜์˜ ์ฝ”๋“œ์—์„œ @Autowired ๋กœ MemberService ํด๋ž˜์Šค์˜ ์ƒ์„ฑ์ž์— MemberRepository ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ฃผ์ž…๋ฐ›๋Š” ์ด์œ ๋Š” ์˜์กด์„ฑ ์ฃผ์ž…(Dependency Injection) ์„ ํ†ตํ•ด ๋Š์Šจํ•œ ๊ฒฐํ•ฉ(Loose Coupling) ์„ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ฉ์ž…๋‹ˆ๋‹ค.
    • ์ด๋Š” ๊ฐ์ฒด์ง€ํ–ฅ ์„ค๊ณ„์—์„œ ๋งค์šฐ ์ค‘์š”ํ•œ ์›์น™ ์ค‘ ํ•˜๋‚˜๋กœ, ํด๋ž˜์Šค ๊ฐ„์˜ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถฐ ์ฝ”๋“œ์˜ ์œ ์—ฐ์„ฑ๊ณผ ํ™•์žฅ์„ฑ์„ ๋†’์ด๋Š” ๋ฐ ๊ธฐ์—ฌํ•ฉ๋‹ˆ๋‹ค.

1๏ธโƒฃ ์ „์ฒด ์ฝ”๋“œ.

// MemberRepository
import com.devkobe.hello_spring.domain.Member;
import java.util.List;
import java.util.Optional;


public interface MemberRepository {
	Member save(Member member);
	Optional<Member> findById(Long id);
	Optional<Member> findByName(String name);
	List<Member> findAll();
}

// MemoryMemberRepository
import com.devkobe.hello_spring.domain.Member;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.springframework.stereotype.Repository;

@Repository
public class MemoryMemberRepository implements MemberRepository {

	private static Map<Long, Member> store = new HashMap<>();
	private static long sequence = 0L;

	@Override
	public Member save(Member member) {
		member.setId(++sequence);
		store.put(member.getId(), member);
		return member;
	}

	@Override
	public Optional<Member> findById(Long id) {
		return Optional.ofNullable(store.get(id));
	}

	@Override
	public Optional<Member> findByName(String name) {
		return store.values().stream()
				.filter(member -> member.getName().equals(name))
				.findAny();
	}

	@Override
	public List<Member> findAll() {
		return new ArrayList<>(store.values());
	}

	public void clearStore() {
		store.clear();
	}
}

// MemberService
import com.devkobe.hello_spring.domain.Member;
import com.devkobe.hello_spring.repository.MemberRepository;
import com.devkobe.hello_spring.repository.MemoryMemberRepository;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MemberService {
	private final MemberRepository memberRepository;

	@Autowired
	public MemberService(MemberRepository memberRepository) {
		this.memberRepository = memberRepository;
	}

	/*
	 * ํšŒ์› ๊ฐ€์ž…
	 */
	public Long join(Member member) {

		validateDuplicateMember(member); // ์ค‘๋ณต ํšŒ์› ๊ฒ€์ฆ
		memberRepository.save(member);
		return member.getId();
	}

	private void validateDuplicateMember(Member member) {
		memberRepository.findByName(member.getName())
				.ifPresent(m -> {
					throw new IllegalStateException("์ด๋ฏธ ์กด์žฌํ•˜๋Š” ํšŒ์›์ž…๋‹ˆ๋‹ค.");
				});
	}

	/*
	 * ์ „์ฒด ํšŒ์› ์กฐํšŒ
	 */
	public List<Member> findMembers() {
		return memberRepository.findAll();
	}

	public Optional<Member> findOne(Long memberId) {
		return memberRepository.findById(memberId);
	}
}

2๏ธโƒฃ ๊ตฌ์ฒด์ ์ธ ์ด์œ .

  • 1. ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•œ ์œ ์—ฐ์„ฑ ํ™•๋ณด.
    • MemberRepository ๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋กœ, MemoryMemberRepository ์™€ ๊ฐ™์€ ๊ตฌํ˜„์ฒด๋“ค์ด ์ด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
      • ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด MemberService ๋Š” ํŠน์ • ๊ตฌํ˜„์ฒด์— ์˜์กดํ•˜์ง€ ์•Š์œผ๋ฉฐ, MemberRepository ์ธํ„ฐํŽ˜์ด์Šค์— ์˜์กดํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
        • ์ด๋Š” MemberService ๊ฐ€ MemoryMemberRepository ๋‚˜ ๋‹ค๋ฅธ MemberRepository ๊ตฌํ˜„์ฒด(JdbcMemberRepository, JpaMemberRepository ๋“ฑ)์— ์‰ฝ๊ฒŒ ๊ต์ฒด๋  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
          • ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‚˜์ค‘์— ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์•„๋‹Œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ํšŒ์› ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ „ํ™˜ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, MemoryMemberRepository ๋Œ€์‹  ์ƒˆ๋กœ์šด ๊ตฌํ˜„์ฒด๋ฅผ ์ฃผ์ž…ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
  • 2. ๋Š์Šจํ•œ ๊ฒฐํ•ฉ.
    • MemberService ๋Š” MemberRepository ์ธํ„ฐํŽ˜์ด์Šค์—๋งŒ ์˜์กดํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์–ด๋–ค ๊ตฌํ˜„์ฒด๊ฐ€ ์‹ค์ œ๋กœ ์‚ฌ์šฉ๋ ์ง€๋Š” ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๊ฐ€ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค.
      • ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด MemberService ๋Š” ๊ตฌํ˜„์ฒด๊ฐ€ ๋ฌด์—‡์ธ์ง€ ์•Œ ํ•„์š”๊ฐ€ ์—†์œผ๋ฏ€๋กœ, ๊ตฌํ˜„์ฒด๊ฐ€ ๋ณ€๊ฒฝ๋˜๋”๋ผ๋„ MemberService ๋ฅผ ์ˆ˜์ •ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
    • ์ด ๋ฐฉ์‹์€ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.
      • ์ƒˆ๋กœ์šด ์ €์žฅ์†Œ ๋ฐฉ์‹์ด ๋„์ž…๋˜๋”๋ผ๋„, ๊ธฐ์กด ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๊ณ  ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • 3. ์Šคํ”„๋ง์˜ ์˜์กด์„ฑ ์ฃผ์ž… ๋ฉ”์ปค๋‹ˆ์ฆ˜ ํ™œ์šฉ.
    • ์Šคํ”„๋ง์€ ์ž๋™์œผ๋กœ @Autowired ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ ์ ˆํ•œ MemberRepository ๊ตฌํ˜„์ฒด๋ฅผ ์ฐพ์•„ ์ฃผ์ž…ํ•ฉ๋‹ˆ๋‹ค.
      • MemoryMemberRepository ํด๋ž˜์Šค์— @Repository ์• ๋…ธํ…Œ์ด์…˜์ด ๋ถ™์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ์ด ํด๋ž˜์Šค๋ฅผ MemberRepository ํƒ€์ž…์˜ ๋นˆ์œผ๋กœ ์ธ์‹ํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
    • ์Šคํ”„๋ง์€ MemberRepository ์ธํ„ฐํŽ˜์ด์Šค ํƒ€์ž…์˜ ๋นˆ์„ ์ฃผ์ž…ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ, ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•ด ์ฃผ์ž…ํ•ฉ๋‹ˆ๋‹ค.
      • ์ด ์˜ˆ์ œ์—์„œ๋Š” MemoryMemberRepository ๊ฐ€ ์ฃผ์ž…๋ฉ๋‹ˆ๋‹ค.

3๏ธโƒฃ ๊ฒฐ๋ก .

  • ์ด๋Ÿฌํ•œ ์„ค๊ณ„๋Š” ์ฝ”๋“œ์˜ ์œ ์—ฐ์„ฑ๊ณผ ํ…Œ์ŠคํŠธ ์šฉ์ด์„ฑ์„ ํฌ๊ฒŒ ํ–ฅ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.
    • ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ, MemberService ๋Š” ํŠน์ • ๊ตฌํ˜„์ฒด์— ๊ตฌ์• ๋ฐ›์ง€ ์•Š๊ณ  ๋‹ค์–‘ํ•œ ํ™˜๊ฒฝ์—์„œ ์žฌ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
      • ๋˜ํ•œ, ์ด๋Š” ์Šคํ”„๋ง์˜ DI ์›์น™์— ๋”ฐ๋ผ, ์ปดํฌ๋„ŒํŠธ ๊ฐ„์˜ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”๊ณ , ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ๋ณ€ํ™”์— ์ž˜ ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค๊ณ„ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.