SPRING/INFLEARN

[๊ฐ•์˜] ์Šคํ”„๋ง ํ•ต์‹ฌ ์›๋ฆฌ - ๊ธฐ๋ณธํŽธ 1

ozllzL 2021. 5. 4. 00:11

 

์ด๋ฒˆ์—” ์Šคํ”„๋ง ํ•ต์‹ฌ์›๋ฆฌ

inf.run/wr1v

 

์Šคํ”„๋ง ํ•ต์‹ฌ ์›๋ฆฌ - ๊ธฐ๋ณธํŽธ - ์ธํ”„๋Ÿฐ | ๊ฐ•์˜

์Šคํ”„๋ง ์ž…๋ฌธ์ž๊ฐ€ ์˜ˆ์ œ๋ฅผ ๋งŒ๋“ค์–ด๊ฐ€๋ฉด์„œ ์Šคํ”„๋ง์˜ ํ•ต์‹ฌ ์›๋ฆฌ๋ฅผ ์ดํ•ดํ•˜๊ณ , ์Šคํ”„๋ง ๊ธฐ๋ณธ๊ธฐ๋ฅผ ํ™•์‹คํžˆ ๋‹ค์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค., ์Šคํ”„๋ง ํ•ต์‹ฌ ์›๋ฆฌ๋ฅผ ์ดํ•ดํ•˜๊ณ , ์„ฑ์žฅํ•˜๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋˜์–ด๋ณด์„ธ์š”! ๐Ÿ“ฃ ํ™•์ธํ•ด์ฃผ

www.inflearn.com

์ถœ์ฒ˜:  ๊น€์˜ํ•œ ๊ฐ•์‚ฌ๋‹˜ ์Šคํ”„๋ง ํ•ต์‹ฌ ์›๋ฆฌ-  ๊ธฐ๋ณธํŽธ


EJB๋Š” ๋„ˆ๋ฌด ์–ด๋ ค์› ์Œ

ใ„ด---> EJB ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๋Œ€์ฒดํ•˜๋Š” ์Šคํ”„๋ง
ใ„ด---> EJB ์—”ํ‹ฐํ‹ฐ๋นˆ์„ ๋Œ€์ฒดํ•˜๋Š” ํ•˜์ด๋ฒ„๋„ค์ดํŠธ -> ์ž๋ฐ” ํ‘œ์ค€ JPA

ํ˜„์žฌ : JPA์˜ ๊ตฌํ˜„์ฒด๋กœ ํ•˜์ด๋ฒ„๋„ค์ดํŠธ๋ฅผ ์ฃผ๋กœ ์‚ฌ์šฉํ•จ

 

1.๊ฐ์ฒด ์ง€ํ–ฅ ์„ค๊ณ„์™€ ์Šคํ”„๋ง

- ์Šคํ”„๋ง์ด๋ž€?

์Šคํ”„๋ง ์ƒํƒœ๊ณ„
ํ•„์ˆ˜

์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ,์Šคํ”„๋ง ๋ถ€ํŠธ

 

์„ ํƒ
์Šคํ”„๋ง ๋ฐ์ดํ„ฐ(CRUD๊ธฐ๋Šฅ, JPA๋ฅผ ๊ฐ€์žฅ ๋งŽ์ด ์”€),

์Šคํ”„๋ง ์„ธ์…˜, ์Šคํ”„๋ง ์‹œํ๋ฆฌํ‹ฐ, ์Šคํ”„๋ง RestDocs(API ๋ฌธ์„œํ™”), ์Šคํ”„๋ง ๋ฐฐ์น˜(๋ฐฐ์น˜ ์ฒ˜๋ฆฌ), ์Šคํ”„๋ง ํด๋ผ์šฐ๋“œ ๋“ฑ...

๋” ๋ณด๊ณ  ์‹ถ์œผ๋ฉด https://spring.io/projects

 

Spring | Projects

Spring Framework Provides core support for dependency injection, transaction management, web apps, data access, messaging, and more.

spring.io

  • ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ
    ํ•ต์‹ฌ ๊ธฐ์ˆ  : ์Šคํ”„๋ง DI(Dependency Injection ์˜ ์•ฝ์ž, ์˜์กด์„ฑ ์ฃผ์ž…) ์ปจํ…Œ์ด๋„ˆ, AOP, ์ด๋ฒคํŠธ, ๊ธฐํƒ€
    ์›น ๊ธฐ์ˆ  : ์Šคํ”„๋ง MVC, ์Šคํ”„๋ง WebFlux
    ๋ฐ์ดํ„ฐ ์ ‘๊ทผ ๊ธฐ์ˆ  : ํŠธ๋žœ์ ์…˜, JDBC, ORM, XML ์ง€์›
    ๊ธฐ์ˆ  ํ†ตํ•จ : ์บ์‹œ, ์ด๋ฉ”์ผ, ์›๊ฒฉ์ ‘๊ทผ, ์Šค์ผ€์ค„๋ง
    ํ…Œ์ŠคํŠธ : ์Šคํ”„๋ง ๊ธฐ๋ฐ˜ ํ…Œ์ŠคํŠธ ์ง€์›
    ์–ธ์–ด: ์ฝ”ํ‹€๋ฆฐ, ๊ทธ๋ฃจ๋น„
    ->์Šคํ”„๋ง ํ”„๋ ˆ์ž„ ์›Œํฌ์˜ ๊ธฐ์ˆ ๋“ค์„ ํŽธ๋ฆฌํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๊ฒŒ ํ•ด ์ฃผ๋Š” ์Šคํ”„๋ง๋ถ€ํŠธ

  • ์Šคํ”„๋ง ๋ถ€ํŠธ
    ๋‹จ๋…์œผ๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์Šคํ”„๋ง ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‰ฝ๊ฒŒ ์ƒ์„ฑ
    Tomcat(์›น ์„œ๋ฒ„) ๋‚ด์žฅ
    starter ์ข…์†์„ฑ ์ œ๊ณต
    ์Šคํ”„๋ง๊ณผ 3rd parth ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž๋™ ๊ตฌ์„ฑ, ๋ฉ”์ด์ € ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์˜ ๋ฒ„์ „์„ ์•Œ์•„์„œ ์ฑ™๊ฒจ์คŒ
    ๋ฉ”ํŠธ๋ฆญ,์ƒํƒœ ํ™•์ธ, ์™ธ๋ถ€ ๊ตฌ์„ฑ ๊ฐ€ํŠผ ํ”„๋กœ๋•์…˜ ์ค€๋น„ ๊ธฐ๋Šฅ ์ œ๊ณต
    ๊ด€๋ก€์— ์˜ํ•œ ๊ฐ„๊ฒฐํ•œ ์„ค์ •
    ์Šคํ”„๋ง ํ”„๋ ˆ์ž„์›Œํฌ์™€ ๋ณ„๋„๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์€ ์•„๋‹˜

์Šคํ”„๋ง์˜ ํ•ต์‹ฌ  ์ปจ์…‰

๊ฐ์ฒด์ง€ํ–ฅ ์–ธ์–ด(JAVA) ๊ฐ€ ๊ฐ€์ง„ ๊ฐ•๋ ฅํ•œ ํŠน์ง•(๋‹คํ˜•์„ฑ)์„ ์‚ด๋ ค๋‚ด๋Š” ํ”„๋ ˆ์ž„์›Œํฌ

์ข‹์€ ๊ฐน์ฑ„ ์ง€ํ–ฅ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ฃผ๋Š” ํ”„๋ ˆ์ž„์›Œํฌ

 

- ์ข‹์€ ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด๋ž€?

๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ํŠน์ง• : ์œ ์—ฐํ•˜๊ณ  ๋ณ€๊ฒฝ์ด ์šฉ์ด, ๊ฐ์ฒด๋“ค์˜ ๋ชจ์ž„ -> ๋‹คํ˜•์„ฑ
์œ ์—ฐํ•˜๊ณ  ๋ณ€๊ฒฝ์ด ์šฉ์ด, ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ์„ค๊ณ„

์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์•ˆ์ •์ ์œผ๋กœ ์„ค๊ณ„ํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ค‘์š”ํ•˜๋‹ค.

 

- ์ข‹์€ ๊ฐ์ฒด ์ง€ํ–ฅ ์„ค๊ณ„์˜ 5๊ฐ€์ง€ ์›์น™(SOLID)

SPR ๋‹จ์ผ ์ฑ…์ž„ ์›์น™ (Single Responsibility principle)

ํ•œ ํด๋ž˜์Šค๋Š” ํ•˜๋‚˜์˜ ์ฑ…์ž„. ๋ณ€๊ฒฝ์ด ์žˆ์„ ๋•Œ ํŒŒ๊ธ‰ ํšจ๊ณผ๊ฐ€ ์ ์œผ๋ฉด ๋‹จ์ผ ์ฑ…์ž„ ์›์น™์„ ์ž˜ ๋”ฐ๋ฅธ ๊ฒƒ.

OCP ๊ฐœ๋ฐฉ-ํŒจ์‡„ ์›์น™ (Open/Closed principle)

ํ™•์žฅ์—๋Š” ์—ด๋ ค์žˆ์ง€๋งŒ ๋ณ€๊ฒฝ์—๋Š” ๋‹ซํ˜€ ์žˆ๊ฒŒ ํ•œ๋‹ค. ๋ณ€๊ฒฝ์„ ํ•˜์ง€ ์•Š์•„๋„ ํ™•์žฅ์ด ์šฉ์ดํ•˜๋„๋ก ํ•œ๋‹ค.

LSP ๋ฆฌ์Šค์ฝ”ํ”„ ์น˜ํ™˜ ์›์น™ (Liskov substitution principle)

์›์น™์„ ์ง€ํ‚จ๋‹ค. goFrontํ•ด๋†“๊ณ  ๋’ค๋กœ๊ฐ€๋ฉด x  

ISP ์ธํ„ฐํŽ˜์ด์Šค ๋ถ„๋ฆฌ ์›์น™ (Interface segration principle)

ํŠน์ • ํด๋ผ์ด์–ธํŠธ๋ฅผ ์œ„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค ์—ฌ๋Ÿฌ ๊ฐœ๊ฐ€ ๋ฒ”์šฉ ์ธํ„ฐํŽ˜์ด์Šค ํ•˜๋‚˜๋ณด๋‹ค ๋‚ซ๋‹ค.

DIP ์˜์กด๊ด€๊ณ„ ์—ญ์ „ ์›์น™ (Dependency inversion principle)

๊ตฌํ˜„ ํด๋ž˜์Šค๊ฐ€ ์•„๋‹Œ ์ธํ„ฐํŽ˜์ด์Šค์— ์˜์กดํ•ด์•ผ ํ•œ๋‹ค.

 

ํ•˜์ง€๋งŒ ๋‹คํ˜•์„ฑ ๋งŒ์œผ๋กœ๋Š” OCP์™€ DIP๋ฅผ ์ง€ํ‚ฌ ์ˆ˜ ์—†๋‹ค.

 

- ๊ฐ์ฒด ์ง€ํ–ฅ ์„ค๊ณ„์™€ ์Šคํ”„๋ง

์Šคํ”„๋ง์€ ๋‹คํ˜•์„ฑ + OCP, DIP๋ฅผ ๊ฐ€๋Šฅํ•˜๊ฒŒ ์ง€์›ํ•œ๋‹ค.

์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋จผ์ € ๋งŒ๋“ค๊ณ  ๊ตฌํ˜„ํ•˜๋Š”๊ฒŒ ์ด์ƒ์  -> ํ–ฅํ›„์— ํ•„์š”ํ•˜๋ฉด ๋„์ž…๋„ ๊ดœ์ฐฎ๋‹ค

 

2. ์˜ˆ์ œ๋งŒ๋“ค๊ธฐ

- ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

start.spring.io/

์ด๋ ‡๊ฒŒ ์„ค์ • ํ›„ GENERATE

ํ•˜๋‹จ์ฒ˜๋Ÿผ ์„ค์ •ํ•ด์•ผ ๋” ๋น ๋ฅด๊ฒŒ ๋นŒ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

File->Settings->Gradle

 

- ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ๊ณผ ์„ค๊ณ„

ํšŒ์›

  • ๊ฐ€์ž…, ์กฐํšŒ ๊ฐ€๋Šฅ
  • ์ผ๋ฐ˜, VIP ๋“ฑ๊ธ‰ ์žˆ์Œ
  • ํšŒ์› ๋ฐ์ดํ„ฐ๋Š” ์ž์ฒด DB๋ฅผ ๊ตฌ์ถ•ํ•˜๊ฑฐ๋‚˜ ์™ธ๋ถ€ ์‹œ์Šคํ…œ๊ณผ ์—ฐ๋™ํ•  ์ˆ˜ ์žˆ๋‹ค.(๋ฏธํ™•์ •)

์ฃผ๋ฌธ๊ณผ ํ• ์ธ ์ •์ฑ…

  • ํšŒ์›์€ ์ƒํ’ˆ์„ ์ฃผ๋ฌธํ•  ์ˆ˜ ์žˆ์Œ
  • ํšŒ์› ๋“ฑ๊ธ‰์— ๋”ฐ๋ผ ํ• ์ธ ์ •์ฑ…์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Œ
  • ๋ชจ๋“  VIP๋Š” 1000์› ๊ณ ์ • ๊ธˆ์•ก ํ• ์ธ (๋ฏธํ™•์ •)

- ํšŒ์› ๋„๋ฉ”์ธ ์„ค๊ณ„

์Šคํ”„๋ง์„ ๋นผ๊ณ  ํ•ด๋ณธ๋‹ค.

 

- ํšŒ์› ๋„๋ฉ”์ธ ๊ฐœ๋ฐœ

1. ๋ฉค๋ฒ„, ๋“ฑ๊ธ‰ ์—”ํ‹ฐํ‹ฐ

//Grade.java
public enum Grade {
    BASIC,
    VIP
}
//Member.java
public class Member {
    private Long id;
    private String name;
    private Grade grade;

    public void setId(Long id) {
        this.id = id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setGrade(Grade grade) {
        this.grade = grade;
    }

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public Grade getGrade() {
        return grade;
    }

    public Member(Long id, String name, Grade grade) {
        this.id = id;
        this.name = name;
        this.grade = grade;
    }
}

2. ๋ฉ”๋ชจ๋ฆฌ ์ธํ„ฐํŽ˜์ด์Šค

//MemberRepository.java
public interface MemberRepository {
    void save(Member member);
    Member findById(Long memberId);
}

 

๋ฉ”๋ชจ๋ฆฌ ๊ตฌํ˜„

//MemoryMemberRepository.java
public class MemoryMemberRepository implements MemberRepository {
    private static Map<Long,Member> store = new HashMap<>();//์‹ค๋ฌด์—์„œ๋Š” concurrency map ์‚ฌ์šฉ

    @Override
    public void save(Member member){
        store.put(member.getId(), member);
    }

    @Override
    public Member findById(Long memberId) {
        return store.get(memberId);
    }
}

3. ์„œ๋น„์Šค ์ธํ„ฐํŽ˜์ด์Šค

//MemberService.java
public interface MemberService {
    void join(Member member);
    Member findMember(Long memberId);
}

์„œ๋น„์Šค ๊ตฌํ˜„

//MemberServiceImpl.java
public class MemberServiceImpl implements MemberService{

    private final MemberRepository memberRepository = new MemoryMemberRepository();
    @Override
    public void join(Member member) {
        memberRepository.save(member);
    }

    @Override
    public Member findMember(Long memberId) {
        return memberRepository.findById(memberId);
    }
}

์ถ”์ƒํ™”์™€ ๊ตฌํ˜„์ฒด๋ฅผ ๋ชจ๋‘ ์˜์กดํ•œ๋‹ค -> DIP์— ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.

MemverServiceImpl์˜

private final MemberRepository memberRepository = new MemoryMemberRepository(); 

์ด ๋ฌธ์žฅ์—์„œ MemberRepository๋ฅผ ์„ ์–ธํ•จ์œผ๋กœ์จ ์ธํ„ฐํŽ˜์ด์Šค์— ์˜์กดํ•˜๊ณ  ์žˆ์œผ๋‚˜,

๊ตฌํ˜„์ฒด๋ฅผ new MemoryMemberRepository(); ๋กœ ์ง์ ‘ ์ ์–ด์คŒ์œผ๋กœ์จ ๊ตฌํ˜„์ฒด์—๋„ ์˜์กดํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

- ํšŒ์› ๋„๋ฉ”์ธ ์‹คํ–‰๊ณผ ํ…Œ์ŠคํŠธ

Test

์ผ๋ฐ˜ ์ž๋ฐ” ์ฝ”๋“œ๋กœ ์ฒดํฌ๋Š” ๋งค๋ฒˆ ๋กœ๊ทธ์ฐ์–ด์•ผ๋˜๊ณ  ๋ถˆํŽธํ•จ

๊ทธ๋ž˜์„œ ์žˆ๋Š” ๊ธฐ๋Šฅ ํ…Œ์ŠคํŠธ

given, when, then

//MemberServiceTest.java
import static org.assertj.core.api.Assertions.assertThat;//assertThat์‚ฌ์šฉ์„ ์œ„ํ•ด ํ•„์š”

public class MemberServiceTest {
    MemberService memberService = new MemberServiceImpl();
    //Control+Alt+V ์‚ฌ์šฉํ•˜๋ฉด ํŽธ๋ฆฌ

    @Test
    void join(){
        //given
        Member member = new Member(1L, "memberA", Grade.VIP);

        //when
        memberService.join(member);
        Member findMember = memberService.findMember(1L);

        //then
        assertThat(member).isEqualTo(findMember);
    }
}

์‹คํ–‰ &์„ฑ๊ณต

 

- ์ฃผ๋ฌธ๊ณผ ํ• ์ธ ๋„๋ฉ”์ธ ์„ค๊ณ„

์ €์žฅ์†Œ์™€ ํ• ์ธ ์ •์ฑ…๋งŒ ์ ์ ˆํ•˜๊ฒŒ ๋‹ค๋ฅธ ๊ฒƒ์„ ๋ผ์›Œ์ฃผ๋ฉด ๋œ๋‹ค.

์—ญํ• ๋“ค์˜ ํ˜‘๋ ฅ ๊ด€๊ณ„๋ฅผ ๊ทธ๋Œ€๋กœ ์žฌ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ์Œ

 

- ์ฃผ๋ฌธ๊ณผ ํ• ์ธ ๋„๋ฉ”์ธ ๊ฐœ๋ฐœ

 

ํ• ์ธ ์ •์ฑ… ์ธํ„ฐํŽ˜์ด์Šค

//DiscountPolicy.java
public interface DiscountPolicy {
    int discount(Member member, int price);
}

๊ณ ์ •๋œ ํ• ์ธ ์ •์ฑ… ๊ตฌํ˜„

//DiscountPolicy.java
public class FicDiscountPolicy implements DiscountPolicy{

    private int discountFixAmount = 1000;//1000์› ํ• ์ธ

    @Override
    public int discount(Member member, int price) {
        if(member.getGrade() == Grade.VIP)
            return discountFixAmount;
        else
            return 0;
    }
}

์ฃผ๋ฌธ ๊ฐ์ฒด

//Order.java
public class Order {
    private Long memberId;
    private String itemName;
    private int itemPrice;
    private int discountPrice;


    public Order(Long memberId, String itemName, int itemPrice, int discountPrice) {
        this.memberId = memberId;
        this.itemName = itemName;
        this.itemPrice = itemPrice;
        this.discountPrice = discountPrice;
    }

    public void setMemberId(Long memberId) {
        this.memberId = memberId;
    }

    public void setItemName(String itemName) {
        this.itemName = itemName;
    }

    public void setItemPrice(int itemPrice) {
        this.itemPrice = itemPrice;
    }

    public void setDiscountPrice(int discountPrice) {
        this.discountPrice = discountPrice;
    }

    public Long getMemberId() {
        return memberId;
    }

    public String getItemName() {
        return itemName;
    }

    public int getItemPrice() {
        return itemPrice;
    }

    public int getDiscountPrice() {
        return discountPrice;
    }

    @Override
    public String toString() {
        return "Order{" +
                "memberId=" + memberId +
                ", itemName='" + itemName + '\'' +
                ", itemPrice=" + itemPrice +
                ", discountPrice=" + discountPrice +
                '}';
    }
}

์ฃผ๋ฌธ ์ธํ„ฐํŽ˜์ด์Šค

// OrderService.java
public interface OrderService {
    Order createOrder(Long memberID, String itemName, int itemPrice);
}

์ฃผ๋ฌธ ๊ตฌํ˜„

// OrderService.java
public class OrderServiceImpl implements OrderService{
    private final MemberRepository memberRepository = new MemoryMemberRepository();
    private final DiscountPolicy discountPolicy = new FicDiscountPolicy();

    @Override
    public Order createOrder(Long memberID, String itemName, int itemPrice) {

        Member member = memberRepository.findById(memberID);
        int discountPrice = discountPolicy.discount(member,itemPrice);

        return new Order(memberID, itemName, itemPrice, discountPrice);
    }
}

ํ• ์ธ๊ณผ ๊ด€๋ จํ•œ ์ˆ˜์ •์ด ์žˆ์œผ๋ฉด OrderService๋Š” ์ด๊ฑธ ๊ณ ๋ คํ•˜์ง€ ์•Š์•„๋„ ๋จ - ์ž˜ ๋œ ์„ค๊ณ„

 

- ์ฃผ๋ฌธ๊ณผ ํ• ์ธ ๋„๋ฉ”์ธ ์‹คํ–‰๊ณผ ํ…Œ์ŠคํŠธ

๋กœ์ง์œผ๋กœ ํ…Œ์ŠคํŠธ : ์ž˜๋‚˜์˜ด

 

JUnit์œผ๋กœ ํ…Œ์ŠคํŠธ : ์ž˜๋จ

 

์ฒซ ๋ฒˆ์งธ ๋“ฃ๊ณ  ๋‚œ ํ›„๊ธฐ :

์ด ์ด์ „ ์Šคํ”„๋ง ์ž…๋ฌธ๋ถ€ํ„ฐ ๊ฐ•์˜๋ฅผ ๋‹ค ๋“ฃ๊ณ  ๋‹ค์Œ ๊ฐ•์˜์ธ ํ•ต์‹ฌ ์›๋ฆฌ๋ฅผ ๋“ฃ๊ณ  ์žˆ๋‹ค.

์Šคํ”„๋ง ์ž…๋ฌธ์„ ๋“ค์„ ๋•Œ๋Š” ์ด๊ฒŒ ๋ญ”๊ฐ€... ์ด๊ฑฐ ์ด๋ ‡๊ฒŒ ๋ฐฐ์›Œ์„œ ๋˜๊ธด ํ•˜๋Š”๊ฑด๊ฐ€... ํ•˜๋Š” ๊ธฐ๋ถ„์œผ๋กœ ๋๊นŒ์ง€ ๋“ค์—ˆ๋Š”๋ฐ

๊ทธ๊ฑธ ๋‹ค ๋“ฃ๊ณ  ๋‚˜์„œ ํ•ต์‹ฌ์›๋ฆฌ๋ฅผ ๋“ค์œผ๋‹ˆ ์ด์ œ ๊ทธ๋•Œ ํ–ˆ๋˜๊ฒŒ ๋ณด์ด๊ณ  ์ดํ•ด๊ฐ€ ๋˜๋Š” ๊ฒƒ ๊ฐ™๋‹ค.

์—ญ์‹œ ๋๊นŒ์ง€ ํ•ด๋ด์•ผ๋ผ... 

ํ•˜๊ธด ์ด๋ ‡์ง€ ์•Š์•˜๋˜๊ฒŒ ์žˆ์—ˆ๋‚˜ ๋‚ด๊ฐ€ ๋ฐฐ์› ๋˜ ๊ฒƒ ์ค‘์—!

 

๋ณต์Šต ํ›„ ํ›„๊ธฐ : 

๋ญ”๊ฐ€ ์ด์ œ ์ฝ”๋“œ๊ฐ€ ํ•œ ๋ฒˆ๋งŒ ๋ด๋„ ๋ญ˜ ํ•˜๋Š” ๊ฒƒ์ธ์ง€ ์•Œ ์ˆ˜ ์žˆ๋Š” ์ƒํƒœ๋กœ ๋ณด๋‹ˆ๊นŒ ์‹ ๊ธฐํ•จ

์Ÿ์•„์ ธ๋‚˜์˜ค๋Š” ์ƒˆ๋กœ์šด ๋‚ด์šฉ์— ๋†“์ณค๋˜ ๋””ํ…Œ์ผํ•œ ๋ถ€๋ถ„์„ ๋ณผ ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

๊ธฐ์–ต์ด ์•ˆ๋‚˜๋Š” ๋ถ€๋ถ„์ด ๊ฝค ๋งŽ๊ตฐ