항해99 3기

[WIL] 항해99 3기 2주차: 개인 프로젝트 / IoC / DI / Bean

na_o 2021. 9. 26. 22:46
728x90

[개인 프로젝트 : 나만의 블로그 만들기]

 

저번주에는 주특기를 정하고 이번주에 주특기 관련 강의를 들었다

나는 기존에 해왔던 Spring으로 선택했고,

기초강의를 들었다

강의는 SpringBoot를 다뤘다

강의를 다 듣고 요구사항에 맞게 개인 프로젝트를 만드는 거다

추석 연휴 월요일에 강의 듣는 것을 시작해서 금요일에 끝냈다

항해를 시작하기 전에 같은 강의를 산 적이 있어서 똑같은 강의를 두번째 듣고 있었는데

처음 강의를 따라서 할 때는 오류가 안 났었다 하지만

이번에 다시 또 똑같이 따라서 하는데 오류가 자주 났었다

인텔리제이를 설치할 때 디폴트 워크스페이스를 정해주는데, 나는 거기다가 안하고

다른 드라이브에 워크스페이스를 만들어서 프로젝트를 했다

그래서 그런지 컴파일러?를 못 찾는다는 등 에러가 나고

특히 이해가 안 가는건 https://nazero.tistory.com/87

 

SpringBoot 에러) cannot deserialize from object value

항해99를 시작하기 전 구매해서 들었던 강의를 항해99에서 제공을 해줬다 그래서 똑같은 강의를 듣고있는데 아래와 같은 에러가 나는것이다..! com.fasterxml.jackson.databind.exc.InvalidDefinitionException: C..

nazero.tistory.com

강의를 진행하면서 위의 오류가 났었다

항해 시작 전에 강의를 사서 들었을 땐 저런 오류가 안 났었다(그 당시 강의를 들을 때 문제 없이 됐다는 글을 남겨놨다)

프로젝트를 생성한 위치가 다를 뿐이었다

같은 강의를 들었어서 Lombok 등 라이브러리가 미리 설치되어있긴 했다

왜 그 때는 되고 이번엔 안되는건가..ㅠ

쨋든 DTO에서 멤버변수에 final을 없애면서 해결이 되었다

하지만 찜찜하다...final을 떼면 데이터 수정을 막 할 수 있는거 아닌가..?

DTO의 의미가 사라지는 느낌이다

 

 

 


어찌어찌해서 강의를 모두 다 듣고 금요일 오후 5시 반쯤 프로젝트를 시작했다

기본 기능이더라도 이쁘게 하고싶어서 Bulma 템플릿을 가져와서 했다

html을 좀 두시간정도 다듬고 Github에 올린 다음 백쪽을 시작하려고 했다

바로 이전 프로젝트에서 나 포함 Github를 팀원들 모두 잘 몰라서 사용 방법을 익히는데 좀 애먹었다

모든 과정을 터미널로 했었는데 프로젝트가 모두 끝나고 InteliJ의 기능을 이용해서 Git을 사용할 수 있다고 들었다

그래서 InteliJ에서 Git을 쓰려고 시도했다

처음에 내가 내 맘대로 막 눌러서 그런지 Github를 연동시키는게 뜻대로 안됐다

블로그 글을 찾아서 해보는데도 잘 안됐었다

어찌어찌 하다가 한 블로그를 찾아서 비슷하게 따라해보니 드디어 연결이 됐다

https://hermeslog.tistory.com/468

 

[IntelliJ] Git 연동하기

Git은 사실 처음 사용하는 사람들에게 어렵습니다. - Eclipse 에서 SVN 연동해서 사용하던 사람은 더 어렵습니다. 목표 IntelliJ를 이용해서 Git 을 SVN 처럼 사용하기. 개발환경 IntelliJ 2020.3 Git 2.30 Git을..

hermeslog.tistory.com

이걸 한 8시부터 시작해서 오전 1시까지 하고 있었다..ㅎ

그래도 Github에 올리는데 성공해서 다행이다

백엔드쪽을 만드는건 오래 걸리진 않았다

금요일에 1시간정도 만들고(Create, Read) ARC로 테스트까지 했다

토요일에 오전 9시부터 오후 5시까지 해서 요구하는 기능들은 다 완성했다

만드는 과정에서 딱히 막혔던 부분은 없었다

에러가 나봤자 나의 실수로 어노테이션을 빠트려서 나는 에러 정도였다

좀 맘에 걸렸던건 JSP를 쓰고싶었는데 강의에서는 JSP를 쓰지 않았기 때문에

나도 JSP를 쓰지 않았다

심화 강의를 나중에 주는데 그 때 쓸 수 있겠지 하면서 강의의 정석을 따라서 했다

강의에서는 JSP를 안 쓰고 jQuery의 append() 함수를 이용해서 html을 만들었다

결론은 큰 문제 없이 개인 프로젝트를 만들었다


1. 메인페이지

메인페이지로 가면 글들을 조회할 수 있고 수정일이 최근인 글이 가장 위쪽에 뜨도록 정렬했다

하나의 행을 누르면 글의 내용을 볼 수 있고,

체크박스를 하나 누르고 삭제 버튼을 누르면 글 삭제를 할 수 있다

 

 

 

2. 글 쓰기

Bulma의 Modal을 가져와서 사용했다

메인 페이지에서 글쓰기 버튼을 누르면 제목, 작성자, 내용을 입력할 수 있다

모달의 오른쪽 아래에 있는 글쓰기 버튼을 누르면 메인페이지의 글 목록에 추가된다

 

 

 

2. 상세보기

메인 페이지에서 하나의 행을 누르면 이렇게 내용을 볼 수 있다

수정 버튼을 눌러 내용을 수정할 수 있다

 

 

 

3. 수정 페이지

수정 페이지도 Modal을 이용했다

제목, 작성자 이름, 내용을 수정해서 수정하기 버튼을 누르면 '수정되었습니다' 라는 alert이 뜨고

메인페이지가 새로고침된다

 

 

 

3. 글 삭제

글을 삭제하려면 삭제하고싶은 글의 왼쪽에 있는 체크박스를 누르고 삭제 버튼을 누르면

메인페이지가 새로고침되면서 글이 사라진다

 

 

 


강의를 들으면서 SpringBoot의 주요 개념 용어는 언급되지 않았지만

강의를 따라하면 나도 모르게 자연스럽게 DI, IoC, Bean을 사용했을 것이다

 

 

 

[DI(Dependency Injection)]    https://dpdpwl.tistory.com/140

코드상 객체를 직접적으로 만드는게 아닌 객체의 밖에서 객체를 넣어주는(주입) 방식

 

* 코드상 객체를 직접적으로 만드는 것

public class BugService {
    public void countLeg(){
        BugRepository bug = new Fly();
        bug.legCount();
    }
}

new를 통해 코드에 직접 써버리면

다른 객체를 사용하고 싶어도 직접 수정하기 전까진 불가능하다

 

* 객체의 밖에서 객체를 넣어주는 것

public class BugService {
    private BugRepository bugRepository;

    public BugService(BugRepository bugRepository){
        this.bugRepository = bugRepository;
    }

    public void countLeg(){
        bugRepository.legCount();
    }
}

이렇게 생성자로 객체를 받는다면 "의존성을 주입받았다"라고 할 수 있다

 

    @Test
    public void testLeg(){
        BugRepository bug = new LadyBug(); // Fly(), Mantis()... 등등
        BugService bugService = new BugService(bug); //bugService의 생성자로 의존성주입!
        bugService.countLeg();
    }

이제 객체를 생성하고 싶으면 생성자에 객체를 무엇이든 넘겨주면 된다

 

이 개념을 개인 프로젝트의 코드에서 찾아본다면

@Getter
@NoArgsConstructor
@Entity
public class Post extends Timestamped{

    @GeneratedValue(strategy = GenerationType.AUTO)
    @Id
    private Long id;        //글번호
    ...

    public Post(PostRequestDto requestDto) {
        this.title = requestDto.getTitle();
        this.name = requestDto.getName();
        this.content = requestDto.getContent();
    }
    ...
}
@RequiredArgsConstructor
@RestController
public class PostController {

    private final PostRepository postRepository;
    private final PostService postService;

    @PostMapping("/api/posts")
    public Post writePost(@RequestBody PostRequestDto requestDto) {
        Post post = new Post(requestDto);
        return postRepository.save(post);
    }
    ...
}

이 부분인 것 같다

PostController(객체의 밖)에서 PostDto 클래스를 Post에 넣어주고 있다

 

 

 


[IoC(Inversion of Control)]    https://ddingg.tistory.com/70?category=896607

제어권이 역전된 것

일반적인 경우 내가 사용할 의존성은 내가 만들지만

IoC는 내가 사용할 의존성을 대신 만들어줌

의존성을 관리하는 게 자기 자신이 아니라 외부에 의해 주입되기 때문에 Inversion of Control이라고 부름

 

"DI랑 IoC랑 같은 개념인건가..?"

의존성을 주입해주는 을 DI라고 하고

의존성을 대신 만들어주는 상황을 IoC라고 하는 것 같다

 

// 일반적인 경우
public class TestClassController {
    public TestRespository testRespository; // 따로 초기화를 해주지 않음

    public TestClassController(TestRespository testRespository){
        this.testRespository = testRespository;
    }

    @Test
    public void testDoSomthing(){
        testRespository.save();
    }

}

TestClassController를 만들 때 생성자에서 TestRepository 객체를 주입하기 때문에

NullPointException같은 에러는 나지 않는다

 

// @MockBean Annotation을 사용해서 의존성을 주입
public class TestClassController {
    @MockBean
    public TestRespository testRespository; // 따로 초기화를 해주지 않음

    @Test
    public void testDoSomthing(){
        testRespository.save();
    }
}

따로 초기화나 객체를 주입해주지 않아도 문제 없이 동작한다

물론 SpringBoot에 TestRepository를 Bean으로 만들어 사용할거라는 말을 명시해줘야 한다

그것이 @Component 인 것 같다

강의에서

스프링이 자동으로 필요한 클래스를 필요한 곳에 생성하려면
"아, 사용자가 요구하면 자동으로 생성할 클래스 목록이 이거구나"
라고 확인할 수 있어야 하는데,
그 목록에 등록하는 간단한 방법이 컴포넌트 등록이다
컴포넌트 등록하는 방법은 클래스 위에 @Component 어노테이션을 사용하는 것이다
@Component를 적어주고 @RequiredArgsConstructor 와 함께 사용할 경우 스프링이 자동으로 생성한다

라고 한 부분이 있다

다른 클래스에서 final을 쓰고 멤버변수를 적어준 다음 @RequiredArgsConstructor를 쓰면 Spirng이 알아서 클래스를 가져온다 라고 했는데

가져올 클래스에 @Component를 써줘야 알아서 가져온다고 했다

 

 

 


[Bean]    https://ddingg.tistory.com/71?category=896607

IoC 컨테이너가 관리하는 일반적인 객체

new 키워드를 사용해 객체를 만드는 것은 Bean에 포함되지 않는다

InteliJ에서 클래스가 Bean에 등록되어있는지 확인하려면 클래스 옆에 

이 아이콘이 있으면 등록된 거다

 

[Bean 등록 방법]

* Component Scanning

    - @Controller

    - @Repository

    - @Component ...

@SpringBootApplication내부의 Annotaion중 하나인 @ComponentScan이 어디부터 Component를 찾아보라고 알려준다. Component를 찾아보는 행위를 Component Scanning 이라고 한다.

* 직접 등록

    - Bean 설정 파일이 Java 설정파일인지 xml인지에 따라 다르다

    - Java 설정파일일 경우, @Configuration 이라는 어노테이션이 붙어있는데,

      그 안에 @Bean을 사용해 직접 정의할 수 있다

      해당 JavaConfiguration 파일이 Component Scanning에 의해 읽힐 때 IoC 컨테이너에 들어간다

@Configuration
public class JavaConfigurationExample {
    @Bean
    public TestRespository testRespository(){
        return new TestRespository(); //return한 객체가 @Bean에 의해 등록 된다.
    }
}

 

[Bean을 꺼내 쓰는 방법]

@Autowired 어노테이션을 사용하는 것