728x90
반응형

1. Basic Controller

controller 파일을 만들어준다.

/src/main/java/com.example.demo/controller/TeepoController

 

package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class TeepoController {

    @GetMapping("teepo-string")
    @ResponseBody
    public String teepoString(@RequestParam("name") String name) {
        return "hello-template" + name;
    }
}

여기서 @ResponseBody 는 API 응답으로 Body 안에 원하는 데이터를 넣어주겠다는 뜻이다.

 

브라우저에서 접속해보면

return 값이 정상적으로 반환되는 것을 확인할 수 있다.

 

 

2. JSON return Controller

json 형식으로 반환할 땐 아래와 같이 할 수 있다.

    @GetMapping("teepo-api")
    @ResponseBody
    public Teepo teepoApi(@RequestParam("name") String name) {
        Teepo teepo = new Teepo();
        teepo.setName(name);
        return teepo;
    }
    static class Teepo {
        private String name;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }

 

서버를 키고 확인해보면,

이와같이 json 형식으로 데이터를 받은 것을 확인할 수 있다.

 

3. Member 객체 생성

domain 폴더를 만들고 Member 에 대한 객체를 만들어보자.

com.example.demo/domain/Member

package com.example.demo.domain;

public class Member {
    private Long id;
    private String name;

    public Long getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

 

멤버 리포지토리 인터페이스를 만든다.

com.example.demo/repository/MemberRepository

package com.example.demo.repository;

import com.example.demo.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();
}

여기서 Optional 이란 null 값을 처리하기 위해 한 번 감싸서 선언함을 의미한다.

 

리포지토리 메모리 구현체를 파일을 만든다.

com.example.demo/repository/MemoryMemberRepository

package com.example.demo.repository;

import com.example.demo.domain.Member;

import java.util.*;

/**
 * 동시성 문제가 고려되어 있지 않음, 실무에서는 ConcurrentHashMap, AtomicLong 사용 고려
 */
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 List<Member> findAll() {
        return new ArrayList<>(store.values());
    }
    @Override
    public Optional<Member> findByName(String name) {
        return store.values().stream()
                .filter(member -> member.getName().equals(name))
                .findAny();
    }
    public void clearStore() {
        store.clear();
    } 
}

 

4. Member Test

/src/text/java/com.example.demo/repository/MemoryMemberRepositoryTest

package com.example.demo.repository;

import com.example.demo.domain.Member;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import java.util.List;

import static org.assertj.core.api.Assertions.*;

class MemoryMemberRepositoryTest {
    MemoryMemberRepository repository = new MemoryMemberRepository();
    @AfterEach
    public void afterEach() {
        repository.clearStore();
    }
    @Test
    public void save() {
        //given
        Member member = new Member();
        member.setName("spring");
        //when
        repository.save(member);
        //then
        Member result = repository.findById(member.getId()).get();
        assertThat(result).isEqualTo(member);
    }
    @Test
    public void findByName() {
        //given
        Member member1 = new Member();
        member1.setName("spring1");
        repository.save(member1);
        Member member2 = new Member();
        member2.setName("spring2");
        repository.save(member2);
        //when
        Member result = repository.findByName("spring1").get();
        //then
        assertThat(result).isEqualTo(member1);
    }
    @Test
    public void findAll() {
        //given
        Member member1 = new Member();
        member1.setName("spring1");
        repository.save(member1);
        Member member2 = new Member();
        member2.setName("spring2");
        repository.save(member2);
        //when
        List<Member> result = repository.findAll();
        //then
        assertThat(result.size()).isEqualTo(2);
    }
}

여기서 get 메소드는 Optional 객체 에서 데이터를 빼오는 방법이다.

 

5. Member Service

/src/main/java/com.example.demo/service/MemberService

package com.example.demo.service;

import com.example.demo.domain.Member;
import com.example.demo.repository.MemberRepository;
import com.example.demo.repository.MemoryMemberRepository;

import java.util.List;
import java.util.Optional;

public class MemberService {
    private final MemberRepository memberRepository = new
            MemoryMemberRepository();
    /**
     * 회원가입
     */
    public Long join(Member member) {
        validateDuplicateMember(member); //중복 회원 검증 memberRepository.save(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);
    } }

 

6. Member Service Test

먼저 회원 서비스 코드를 DI 가능하게 변경한다.

/src/main/java/com.example.demo/service/MemberService

    ...
    
    private final MemberRepository memberRepository;

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

 

클래스 안에서 마우스를 클릭하고 command + shift + t 를 누르면 Test를 자동으로 생성해줄 수 있다.

 

/src/test/java/com/example.demo/service/MemberServiceTest

package com.example.demo.service;

import com.example.demo.domain.Member;
import com.example.demo.repository.MemoryMemberRepository;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.*;

class MemberServiceTest {

    MemberService memberService;
    MemoryMemberRepository memberRepository;

    @BeforeEach
    public void beforeEach() {
        memberRepository = new MemoryMemberRepository();
        memberService = new MemberService(memberRepository);
    }
    @AfterEach
    public void afterEach() {
        memberRepository.clearStore();
    }
    @Test
    public void 회원가입() throws Exception {
        //Given
        Member member = new Member();
        member.setName("hello");
        //When
        Long saveId = memberService.join(member);
        //Then
        Member findMember = memberRepository.findById(saveId).get();
        assertEquals(member.getName(), findMember.getName());
    }
    @Test
    public void 중복_회원_예외() throws Exception {
        //Given
        Member member1 = new Member();
        member1.setName("spring");
        Member member2 = new Member();
        member2.setName("spring");

        //When
        memberService.join(member1);
        IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2));//예외가 발생해야 한다.

        assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
    }
}

 

 

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

Service 를 사용하는 Controller를 만들어 보자.

/src/main/java/com.example.demo/controller/MemberController

package com.example.demo.controller;

import com.example.demo.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

@Controller
public class MemberController {

    private final MemberService memberService;

    @Autowired
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
}

생성자에 @Autowired 가 있으면 스프링이 연관된 객체를 스프링 컨테이너에서 찾아서 넣어준다. 이렇게 객체 의존관계를 외부에서 넣어주는 것을 DI (Dependency Injection), 의존성 주입이라 한다.

@Controller 가 있으면 스프링 빈으로 자동 등록된다.

 

 

Service 와 Repository에도 annotation 을 달아주자.

...
@Service
public class MemberService {
...

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

 

...
@Repository
public class MemoryMemberRepository implements MemberRepository {
...

 

8. 자바 코드로 직접 스프링 빈 등록하기

회원 서비스와 회원 리포지토리의 @Service, @Repository, @Autowired 애노테이션을 제거하고 진행한다.

 

/src/test/java/com.example.demo/SpringConfig

package com.example.demo;

import com.example.demo.repository.MemberRepository;
import com.example.demo.repository.MemoryMemberRepository;
import com.example.demo.service.MemberService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringConfig {

    @Bean
    public MemberService memberService() {
        return new MemberService(memberRepository());
    }
    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
}

이렇게 하면 스프링이 실행되면서 의존성을 주입해준다.

728x90
반응형
728x90
반응형

1. Java 11 과 intelliJ를 설치한다.

 

https://www.oracle.com/java/technologies/downloads/#java11-mac

 

Download the Latest Java LTS Free

Subscribe to Java SE and get the most comprehensive Java support available, with 24/7 global access to the experts.

www.oracle.com

 

https://www.jetbrains.com/idea/download/#section=mac

 

Download IntelliJ IDEA: The Capable & Ergonomic Java IDE by JetBrains

Download the latest version of IntelliJ IDEA for Windows, macOS or Linux.

www.jetbrains.com

 

2. 스프링 부트 스타터 사이트로 이동하고 프로젝트를 만든다.

https://start.spring.io/

 

 

3. 아래처럼 생성해주고, intelliJ 에서 build.gradle 파일로 프로젝트를 열어준다.

 

4. build 버튼을 눌러서main 함수를 실행해본다.

터미널 로그를 확인해보면 8080 포트에 서버가 동작하는 것을 확인할 수 있다.

 

5. localhost:8080 으로 들어가본다.

 

이렇게 뜨면 잘 된 것이다.

 

참고로 아래와 같이 설정을 해두면 기존보다 빨리 build 할 수 있다.

 

6. 화면을 보여주기위해 html파일을 만들어보자.

src/main/resources/static/index.html

<!DOCTYPE HTML>
    <html>
<head>
    <title>Hello</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /
</head>
<body>
Hello
<a href="/hello">hello</a>
</body>
    </html>

 

다시 서버를 실행해보면,

잘 뜨는 것을 확인할 수 있다.

 

728x90
반응형

+ Recent posts