• Home
  • About
    • on Weekend photo

      on Weekend

      ๐™Ž๐™ฉ๐™ช๐™™๐™ฎ๐™ž๐™ฃ๐™œ

    • Learn More
    • Instagram
    • Github
  • Archive
    • All Posts
    • All Tags
    • All Categories
  • Categories
    • Problem Solving
    • TIL
    • Study
    • Etc
    • ํ•„์‚ฌ
  • Projects

Spring Study - 3

08 Dec 2020

3. ํšŒ์› ๊ด€๋ฆฌ ์˜ˆ์ œ - ๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ

๋ชฉ์ฐจ

  1. ๋น„์ฆˆ๋‹ˆ์Šค ์š”๊ตฌ์‚ฌํ•ญ ์ •๋ฆฌ
  2. ํšŒ์› ๋„๋ฉ”์ธ๊ณผ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ๋งŒ๋“ค๊ธฐ
  3. ํšŒ์› ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ์ž‘์„ฑ
  4. ํšŒ์› ์„œ๋น„์Šค ๊ฐœ๋ฐœ
  5. ํšŒ์› ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ

์ˆ˜๊ฐ• ์ฝ”์Šค๋Š” ์ธํ”„๋Ÿฐ ์Šคํ”„๋ง ์ž…๋ฌธ ๊ฐ•์˜๋ฅผ ๋“ฃ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.


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

๋‹จ์ˆœํ•œ ๋น„์ฆˆ๋‹ˆ์Šค๋กœ ์‹ค์Šต ์ง„ํ–‰. ๋˜ํ•œ, ์•„์ง ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ์ •ํ•ด์ง€์ง€ ์•Š์•˜์ง€๋งŒ ๊ฐœ๋ฐœ์„ ์ง„ํ–‰ํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์„ ๊ฐ€์ •.

  • ๋ฐ์ดํ„ฐ : ํšŒ์›ID, ์ด๋ฆ„
  • ๊ธฐ๋Šฅ : ํšŒ์› ๋“ฑ๋ก, ์กฐํšŒ
์ผ๋ฐ˜์ ์ธ ์›น ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ตฌ์กฐ

์ผ๋ฐ˜์ ์ธ ์›น ์•ฑ ๊ตฌ์กฐ๋ฅผ ๋”ฐ๋ผ๊ฐˆ ์˜ˆ์ •.

  1. ์ปจํŠธ๋กค๋Ÿฌ : ์›น MVC์˜ ์ปจํŠธ๋กค๋Ÿฌ์˜ ์—ญํ• 
  2. ์„œ๋น„์Šค : ํ•ต์‹ฌ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๊ตฌํ˜„(ex. ํšŒ์› ์ค‘๋ณต๊ฐ€์ž… ๋ถˆ๊ฐ€ ๋“ฑ)
  3. ๋ฆฌํฌ์ง€ํ† ๋ฆฌ : ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ ‘๊ทผ, ๋„๋ฉ”์ธ ๊ฐ์ฒด๋ฅผ DB์— ์ €์žฅํ•˜๊ณ  ๊ด€๋ฆฌ
  4. ๋„๋ฉ”์ธ : ํšŒ์›, ์ฃผ๋ฌธ, ์ฟ ํฐ ๋“ฑ๋“ฑ ์ฃผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅ๋˜๊ณ  ๊ด€๋ฆฌ๋˜๋Š” ๋น„์ฆˆ๋‹ˆ์Šค ๋„๋ฉ”์ธ ๊ฐ์ฒด
ํด๋ž˜์Šค ์˜์กด๊ด€๊ณ„
  • ํšŒ์› ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์œผ๋กœ๋Š” MemberService
  • ํšŒ์›์„ ์ €์žฅํ•˜๋Š” MemberRepository๋Š” interface๋กœ ๊ด€๋ฆฌํ•œ๋‹ค (-> ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ์•„์ง ์„ ์ •๋˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์—)
  • Memory๋กœ ๋‹จ์ˆœํ•˜๊ฒŒ ์ €์žฅํ•˜๋Š” Memory MemberRepository๋กœ ์‚ฌ์šฉํ•œ๋‹ค. ์ถ”ํ›„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๊ฐ€ ์„ ์ •๋˜๋ฉด ๋ฐ”๊ฟ”๋ผ์šธ ์ˆ˜ ์žˆ๋„๋ก ๋ฆฌํฌ์ง€ํ† ๋ฆฌ๋ฅผ interface๋กœ ๊ตฌํ˜„.

ํšŒ์› ๋„๋ฉ”์ธ๊ณผ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ๋งŒ๋“ค๊ธฐ

๋„๋ฉ”์ธ (ํšŒ์› ๊ฐ์ฒด)
  • hello.hellospring์—์„œ domain์ด๋ผ๋Š” ํŒจํ‚ค์ง€๋ฅผ ์ƒ์„ฑํ•˜๊ณ , Member๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
ํšŒ์› ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ์ธํ„ฐํŽ˜์ด์Šค
ํšŒ์› ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ๋ฉ”๋ชจ๋ฆฌ ๊ตฌํ˜„์ฒด
  • implements MemberRepository ํ•ด์ค€ ํ›„ Alt+Insertํ•˜์—ฌ implements Methods ํ•ด์ฃผ Generateํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Map<Long, Member>๋ฅผ ์“ฐ๋ฉด Map์„ inport ํ•ด์ฃผ์–ด์•ผ ํ•˜๋Š”๋ฐ, Alt+Insertํ•˜๊ฑฐ๋‚˜ Ctrl+Spaceํ•˜๋ฉด importํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํ•ด๋‹น ์ฝ”๋“œ์—์„œ HashMap์„ ์‚ฌ์šฉํ•˜๋Š”๋ฐ, ๋™์‹œ์„ฑ ๋ฌธ์ œ๊ฐ€ ๊ณ ๋ ค๋˜์–ด ์žˆ์ง€ ์•Š์œผ๋ฏ€๋กœ ์‹ค๋ฌด์—์„œ๋Š” ConcurrentHashMap, AtomicLong ์‚ฌ์šฉ์„ ๊ณ ๋ คํ•ด์•ผ ํ•œ๋‹ค.
    • ConcurrentHashMap : HashMap์„ thread-safe ํ•˜๋„๋ก ๋งŒ๋“  ํด๋ž˜์Šค์ด๋‹ค. HashMap๊ณผ ๋‹ฌ๋ฆฌ key, value์— null์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋˜ํ•œ ํ‚ค๊ฐ’์ด ์กด์žฌํ•˜๋ฉด ๊ธฐ์กด์˜ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์—†๋‹ค๋ฉด ์ž…๋ ฅํ•œ ๊ฐ’์„ ์ €์žฅํ•œ ๋’ค ๋ฐ˜ํ™˜ํ•˜๋Š” putIfAbsent ๋ฉ”์†Œ๋“œ๊ฐ€ ์กด์žฌํ•œ๋‹ค.
    • AtomicLong : Long ์ž๋ฃŒํ˜•์„ ๊ฐ–๊ณ  ์žˆ๋Š” Wrapping ํด๋ž˜์Šค๋กœ, thread-safe๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ๋‹ค.
  • long sequence๋Š” 1, 2, 3 ๋“ฑ์„ ์ˆœ์„œ๋Œ€๋กœ ๋ฐ›์•„์˜ค๋Š” ๊ฑฐ๋ผ๊ณ  ํ•œ๋‹ค.
    • 0L : ๋ช…์‹œ์ ์œผ๋กœ long type value๋ผ๋Š” ์˜๋ฏธ์ด๋‹ค.
  • member.setId(++sequence)๋กœ id๋ฅผ ์„ธํŒ…ํ•˜๊ณ , store ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅํ•œ๋‹ค.
  • findById์—์„œ return Optional.ofNullable(store.get(id));๋Š” store.get(id)๊ฐ€ null๋กœ ๋ฐ˜ํ™˜๋  ๊ฒƒ์„ ๋Œ€๋น„ํ•˜์—ฌ Optional๋กœ ๊ฐ์‹ธ๋‘๋ฉด, null์ด ๋ฐ˜ํ™˜๋˜์–ด๋„ ๋œ๋‹ค.
  • Java Stream filter (Java8๋ถ€ํ„ฐ ๋“ค์–ด์˜ด)
    • for, foreach ๋Œ€์‹  ๋žŒ๋‹คํ•จ์ˆ˜ํ˜•์‹์œผ๋กœ ๊ฐ„๊ฒฐํ•˜๊ณ  ๊น”๋”ํ•˜๊ฒŒ ์›์†Œ๋ฅผ ๊ณจ๋ผ๋‚ด์–ด ๊ฐ€๊ณต
      • map : ์š”์†Œ๋“ค์„ ํŠน์ • ์กฐ๊ฑด์— ํ•ด๋‹นํ•˜๋Š” ๊ฐ’์œผ๋กœ ๋ณ€ํ™˜ํ•ด์ค€๋‹ค. ๋Œ€,์†Œ๋ฌธ์ž ๋ณ€ํ˜• ๋“ฑ์˜ ์ž‘์—…์„ ํ•˜๊ณ ์‹ถ์„ ๋•Œ ์‚ฌ์šฉ๊ฐ€๋Šฅ
      • filter : ์š”์†Œ๋“ค์„ ์กฐ๊ฑด์— ๋”ฐ๋ผ ๊ฑธ๋Ÿฌ๋‚ด๋Š” ์ž‘์—…. ๊ธธ์ด์˜ ์ œํ•œ, ํŠน์ •๋ฌธ์žํฌํ•จ ๋“ฑ์˜ ์ž‘์—…์„ ํ•˜๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉ๊ฐ€๋Šฅ
      • sorted : ์š”์†Œ ์ •๋ ฌ
    • ์š”์†Œ๋“ค์˜ ๊ฐ€๊ณต์ด ๋๋‚ฌ๋‹ค๋ฉด ๋ฆฌํ„ดํ•  ๊ฒฐ๊ณผ๋ฅผ collect๋ฅผ ํ†ตํ•ด ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค.
  • ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ์˜ ๋™์ž‘ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๋Š” ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์ด ํ…Œ์ŠคํŠธ์ผ€์ด์Šค ์ž‘์„ฑ์ด๋‹ค.

ํšŒ์› ๋ฆฌํฌ์ง€ํ† ๋ฆฌ ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ์ž‘์„ฑ

  • java main method๋ฅผ ํ†ตํ•ด ์‹คํ–‰ํ•˜๊ฑฐ๋‚˜, ์›น์•ฑ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ํ†ตํ•ด ํ•ด๋‹น ๊ธฐ๋Šฅ์„ ์‹คํ–‰ํ•ด๋ณผ ์ˆ˜๋„ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ฐ˜๋ณต์‹คํ–‰ํ•˜๊ธฐ ์–ด๋ ต๊ณ , ์—ฌ๋Ÿฌ ํ…Œ์ŠคํŠธ๋ฅผ ํ•œ๋ฒˆ์— ์‹คํ–‰ํ•˜๊ธฐ ์–ด๋ ต๋‹ค. => Java๋Š” JUnit์„ ์‚ฌ์šฉํ•ด ํ”„๋ ˆ์ž„์›Œํฌ ํ…Œ์ŠคํŠธ ์ง€์›
  • junit.jupiter.api๊ฐ€ ์ง€์›ํ•˜๋Š” Assertions.assertEquals(member, result);์„ ์‚ฌ์šฉํ•˜์—ฌ result์™€ member๊ฐ€ ๊ฐ™์€์ง€ ํ™•์ธํ•œ๋‹ค. (์•ž์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ expected, ๋’ค๊ฐ€ ๊ฒฐ๊ณผ. ์ €์žฅํ–ˆ๋˜ ๋ฉค๋ฒ„๊ฐ€ findํ–ˆ์„ ๋•Œ ํŠ€์–ด๋‚˜์™€์•ผํ•œ๋‹ค.)
  • assertj.core.api๊ฐ€ ์ง€์›ํ•˜๋Š” Assertions๋Š” ์ข€ ๋” ํŽธํ•˜๊ฒŒ ๋˜์–ด์žˆ๋‹ค. Assertions.assertThat(member).isEqualTo(result);๋กœ ์ž‘์„ฑ๋˜๋‹ค๋ณด๋‹ˆ ์˜์–ด ๊ฐ€๋…์„ฑ์ด ์ข‹๋‹ค.
  • ๊ฐ๊ฐ์€ ๊ดœ์ฐฎ๋‹ค๊ฐ€ Class๋กœ test๋ฅผ ๋Œ๋ฆฌ๋ฉด ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธด๋‹ค. findAll()์ด ๋จผ์ € ์˜ฌ๋ผ๊ฐ”๋Š”๋ฐ, findAll()์—์„œ ์ด๋ฏธ spring1, spring2๋ฅผ ์ €์žฅํ•ด์„œ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธด๋‹ค. ๊ทธ๋Ÿฌ๋ฏ€๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ ๋ฒˆ clearํ•ด์•ผ ํ•œ๋‹ค.
  • ๊ฒ€์ฆํ•  ์ˆ˜ ์žˆ๋Š” ํ‹€์„ ๋จผ์ € ๋งŒ๋“ค๊ณ , ์ž‘ํ’ˆ์ด ์™„์„ฑ๋˜๋ฉด ํ‹€์— ๊ฝ‚ํžˆ๋Š”์ง€ ์•ˆ๊ฝ‚ํžˆ๋Š”์ง€๋ฅผ ํ…Œ์ŠคํŠธ ์ฃผ๋„ ๊ฐœ๋ฐœ(TDD)๋ผ๊ณ  ํ•œ๋‹ค. ํ…Œ์ŠคํŠธ๋Š” ์•„์ฃผ ์ค‘์š”ํ•˜๋ฏ€๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ๊นŠ์ด ์žˆ๊ฒŒ ๊ณต๋ถ€ํ•˜๊ธธ ๋ฐ”๋ž€๋‹ค๋Š” ๊ฐ•์‚ฌ๋‹˜์˜ ์กฐ์–ธ.

ํšŒ์› ์„œ๋น„์Šค ๊ฐœ๋ฐœ

  • ๊ฐ’์ด ์žˆ์œผ๋ฉด result.ifPresent๊ฐ€ ๋™์ž‘ํ•œ๋‹ค. Optional๋กœ ํ•œ ๋ฒˆ ๊ฐ์‹ธ๋ฉด, ์˜ต์…”๋„ ์•ˆ์— ์—ฌ๋Ÿฌ ๋ฉ”์†Œ๋“œ๊ฐ€ ์žˆ๊ณ  ์ด๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜๊ฐ€ ์žˆ๋‹ค. ๊ณผ๊ฑฐ์—๋Š” if null ์ด๋Ÿฐ ์‹์œผ๋กœ ์ฝ”๋”ฉํ–ˆ์ง€๋งŒ, null์ผ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์œผ๋ฉด ์˜ต์…”๋„๋กœ ๊ฐ์‹ธ์ค€๋‹ค.
  • result.orElseGet(โ€ฆ) ์„ ์‚ฌ์šฉํ•ด์„œ ์ž์ฃผ ๊บผ๋‚ธ๋‹ค. (์žˆ์œผ๋ฉด ๊บผ๋‚ด๊ณ , ์—†์œผ๋ฉด ๋””ํดํŠธ๊ฐ’์„ ๊บผ๋‚ธ๋‹ค)
  • ์–ด์ฐจํ”ผ Optional๋กœ ๋ฆฌํ„ด์ด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ”๋กœ ifPresent๋กœ ๋ฐ›์•„์ค€๋‹ค.
  • Extract Method๋ฅผ ํ†ตํ•ด ๋ฐ”๋กœ๋ฐ”๋กœ ๋ฉ”์†Œ๋“œ๋ฅผ ๋งŒ๋“ค์–ด์ค„ ์ˆ˜ ์žˆ๋‹ค.
public class MemberService {

    private final MemberRepository memberRepository = new MemoryMemberRepository();

    /* ํšŒ์› ๊ฐ€์ž… */
    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);
    }

}

ํšŒ์› ์„œ๋น„์Šค ํ…Œ์ŠคํŠธ

  • ์ด์ „์— ๋น„ํ•ด ๋น ๋ฅด๊ฒŒ ํ•˜๋Š” ๋ฐฉ๋ฒ• Ctrl + Shift + T : Go to Test
  • Test๋Š” ์‚ฌ์‹ค ๋ฉ”์†Œ๋“œ ์ด๋ฆ„์„ ํ•œ๊ธ€๋กœ ํ•ด๋„ ํฐ ์ƒ๊ด€์ด ์—†๋‹ค.
  • given, when, then ๋ฌธ๋ฒ•
    1. given : ์ด๋Ÿฐ ์ƒํ™ฉ์ด ์ฃผ์–ด์กŒ๋Š”๋ฐ
    2. when : ์ด๊ฑธ ์‹คํ–‰ํ–ˆ์„ ๋•Œ
    3. then : ๊ฒฐ๊ณผ๋กœ ์ด๊ฒŒ ๋‚˜์™€์•ผํ•œ๋‹ค
  • ์ง€๊ธˆ test ๊นŒ์ง€ ๋Œ๋ ธ๋Š”๋ฐ ์•ˆ๋Œ์•„๊ฐ€์„œ ์—๋Ÿฌ ํ•ด๊ฒฐ์ค‘ => spring์œผ๋กœ name์„ ๋‘ ๊ฐœ ์คฌ์–ด์•ผ ํ–ˆ๋Š”๋ฐ, ํ•œ๊ฐœ๋ฅผ Spring์œผ๋กœ ์ค˜์„œ ์—๋Ÿฌ๊ฐ€ ๋‚ฌ์—ˆ๋‹ค.
  • ์„œ๋กœ ๋‹ค๋ฅธ ๋ฆฌํŒŒ์ง€ํ† ๋ฆฌ๋กœ ํ…Œ์ŠคํŠธํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ๊ฐ™์€ ์ธ์Šคํ„ด์Šค๋ฅผ ์“ธ ์ˆ˜ ์žˆ๋„๋ก ๋ฉค๋ฒ„์„œ๋น„์Šค์—์„œ Alt enter ๋ˆŒ๋Ÿฌ์„œ ์™ธ๋ถ€์—์„œ ๋„ฃ์–ด์ฃผ๋„๋ก this.member โ€ฆ ๋กœ ๋ฐ”๊พผ๋‹ค. ๋ฉค๋ฒ„์„œ๋น„์Šค ์ž…์žฅ์—์„œ๋Š” ๋ฉค๋ฒ„๋ฆฌํŒŒ์ง€ํ† ๋ฆฌ๋ฅผ ์™ธ๋ถ€์—์„œ ๋„ฃ์–ด์ฃผ๋ฏ€๋กœ, ์ด๋ฅผ Dependency Induction(DI)๋ผ๊ณ  ํ•œ๋‹ค. ์ด๋Š” ๋‹ค์Œ ์‹œ๊ฐ„์— ๋” ์ž์„ธํžˆ ์•Œ์•„๋ณผ ์˜ˆ์ •.

[๋‹จ์ถ•ํ‚ค]

  • Alt + Insert : Generate
  • Ctrl + Space : import
  • Alt + Shift + Enter : import class (ex. HashMap)
  • Shift + F6 : Rename (๋น ๋ฅด๊ฒŒ ๋ณ€์ˆ˜๋ฅผ ๋ณต๋ถ™ํ•˜๊ณ  ์ด๋ฆ„๋งŒ ๋ฐ”๊พธ๊ธฐ)
  • Ctrl + B : Go to Declaration or Usages
  • Ctrl + W : Extend Selection (ํฌ์ปค์Šค ๋ฒ”์œ„ ํ•œ ๋‹จ๊ณ„์”ฉ ๋Š˜๋ฆฌ๊ธฐ)
  • Ctrl + Shift + Del : Navigate -> Back
  • Ctrl + D : ํฌ์ปค์‹ฑํ•œ ๋‚ด์šฉ์„ ๊ทธ๋Œ€๋กœ duplicateํ•œ๋‹ค
  • Ctrl + Alt + V : return์„ ์ž๋™์œผ๋กœ ํ•ด์ค€๋‹ค.
  • Ctrl + Alt + Shift + T : Extract Method
  • Ctrl + Shift + T : Go to Test

[๋ ˆํผ๋Ÿฐ์Šค]

  • ์ž๋ฐ” ์ŠคํŠธ๋ฆผ ํฌ์ŠคํŠธ


springbackend Share Tweet +1