스프링부트 처음 시작하고 프로젝트 만들기

가온·2024년 10월 12일

나는 원래 AI쪽을 공부했고,
파이썬이 가장 익숙하다.
그래서 백엔드도 파이썬으로 공부했었고, 쭉 그렇게 할까 싶었다.

그런데 한국에서는 파이썬이 백엔드에서 잘 쓰이지 않는다고 한다.
취업을 하거나, 사람을 구하거나 어쨌든 국내에서 백엔드는 자바인 듯 싶었다.
(사실 나는 개발자가 되려고 했던 건 아니었는데...MVP를 만들다보니 개발자 루트를 타고 있다)

  • 실제로 얼마 전 그로스로그 커뮤니티에 다른 분들이 공유해주셨던 설문조사

Stack Over Flow 2024

Most Popular technology
전세계에선 파이썬 점유율이 이렇게나 높은데...

프로그래머스 설문조사 2023

국내로 한정하니 갑자기 치고 들어오는 자바...!

심지어 백엔드로 한정하면 그 격차는 한 없이 벌어진다.

파이썬 백엔드에 인사할 때인가...?

그리고 때마침 팀에 합류 의사를 밝힌 친구가 자바 백엔드 개발자였다. 앞으로도 백엔드는 자바겠지...
마침 프론트엔드 팀원도 합류를 한 시점이라 백엔드 프레임워크를 선택해야했는데, 어차피 파이썬 백엔드도 능숙한 건 아니니까 이참에 스프링부트를 익혀둬야겠다 결심했다.

그래서 이번 MVP는 스프링부트를 사용하기로 했고,
그렇게 쓰는 스프링부트에 입문하고 개발하면서 겪었던 스프링부트 일지다.

IntelliJ 단축키

  • Getter, Setter : Alt + Insert
  • 변수명 전체 변경 : Shift + F6
  • 변수 추출하기 : Ctrl + Alt + V
  • 사용 가능한 리팩토링 옵션 표시 : Ctrl + Shift + Alt + T
  • 테스트 코드 자동 생성 : Ctrl + Shift +T

이제부터 인텔리제이는 내 절친이다.
단축키 너무 유용해

스프링 웹개발 기초

정적 컨텐츠

main → java → resources → 파일명.html 생성

locohost:8080/파일명.html으로 접속 → 정적 페이지

MVC 템플릿 엔진

  • MVC : Model, View, Controller
  • view는 화면에 보여지는 것을
  • Controller는 서버 뒷단에서 일어나는 것을
  • 두 개는 분리하는 게 요즘 추세

API

  • 객체를 반환하면 json으로 변환

  • 객체가 오면 JsonConverter 동작 → json 형식으로 반환
  • 단순 문자면 StringConverter 동작
  • @ResponseBody 사용
    • 문자 반환
      • viewResolver를 사용하지 않음
      • 대신에 HTTP의 BODY에 문자 내용을 직접 반환(HTML BODY TAG를 말하는 것이 아님)
    • 객체 반환

출처 : 인프런 - 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술, 김영한님 (무료 강의)

스프링 백엔드

Test Case

  • 테스트주도개발 TDB
  • 구현 클래스 → 테스트 개발
  • Ctrl + Shift +T : 테스트 코드 자동 생성, 클래스에 클릭

Annotation

  • @AfterEach
    @AfterEach
    public void afterEach() {
        repository.clearStore();
    }
  • 각 매서드 실행마다 돌아와서 다시 실행
  • 저장소, 공용데이터 지워주는 역할
  • @BeforeEach :
    @BeforeEach
    public void beforeEach() {
        memberRepository = new MemoryMemberRepository();
        memberService = new MemberService(memberRepository);
    }
  • 각 테스트 실행 전에 호출된다. 테스트가 서로 영향이 없도록 항상 새로운 객체를 생성하
    고, 의존관계도 새로 맺어준다.

  • @SpringBootTest : 스프링 컨테이너와 테스트를 함께 실행한다.

  • @Transactional : 테스트 케이스에 이 애노테이션이 있으면, 테스트 시작 전에 트랜잭션을 시작하고, 테
    스트 완료 후에 항상 롤백한다. 이렇게 하면 DB에 데이터가 남지 않으므로 다음 테스트에 영향을 주지 않는다.

  • 단위테스트vs통합테스트

    • 단위테스트를 잘 만드는 게 더 좋음
    • 실행시간이라든가…

에러 일지

import 문제

    @GetMapping("/members")
    public String list(Model model) {
        List<Member> members = memberService.findMembers();
        model.addAttribute("members", members);
        return "members/memberList";
    }

MYSQL 연동

  • 문제 : springboot - MYSQL 연동 실패
Execution failed for task ':bootJar'.
> Could not resolve all files for configuration ':runtimeClasspath'.
   > Could not find mysql:mysql-connector-java:8.0.39.
     Required by:
         root project :

1,2번 원인 해결 후

> Task :test FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':test'.
> There were failing tests. See the report at:
  • 원인
    1. dependencies {
      	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
      	runtimeOnly 'com.mysql:mysql-connector-j'
      }
  • runtimeOnly 'mysql:mysql-connector-java' 문법 오류(예전)
  • 스프링부트 3.0 이상에서는 runtimeOnly 'com.mysql:mysql-connector-j'로 변경
  1. application.yml 파일에서 username 오타
  2. application.yml 파일에서url에서 db명 빼먹음

SQL query

  • 문자열 감쌀 때, 쌍따옴표 XX

클래스명 파일명 불일치

public class TimeTraceAop {
//클래스명 빨간 줄
Class 'TimeTraceAop' is public, should be declared in a file named 'TimeTraceAop. java'
  • 문제 : 클래스명에 빨간줄
  • 원인 : 클래스명-파일명 불일치
  • 해결 : 클래스명-파일명 일치시키기

IllegalArgumentException: 메서드에 잘못된 인자가 전달되었을 때 발생.

중괄호 위치

→ 나는 못찾음. 당연함. 나는 눈이 나쁨.

→ gpt도 못찾음 당연함 내가 문제 부분은 빼고 줌.

→클로드는 찾음. 당연함. 내가 매서드 전체 코드 줌

생성자 추가할 때마다 계속

    @Autowired
    public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder, JwtUtil jwtUtil, CPostRepository cPostRepository, CommentsRepository commentsRepository, ScrapRepository scrapRepository) {
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
        this.jwtUtil = new JwtUtil();
        this.cPostRepository = cPostRepository;
        this.commentsRepository = commentsRepository;
        this.scrapRepository = scrapRepository;
    }

괄호 안에도!!! 꼭!! 넣어줘야 함!!!

생성자 인스턴스 변수

Non-static method 'findById(ID)' cannot be referenced from a static context
    @Autowired
    public CommunityPostService(CPostRepository cPostRepository, UserService userService, UserRepository userRepository) {
        this.cPostRepository = cPostRepository;
        this.userService = userService;
        this.userRepository = userRepository;
  • 레포지토리 인스턴스 객체 순으로 작성

  • 매서드에서는 인스턴스 객체를 호출해야 함.

  • 레포지토리xx


    현재 DB는 MYSQL과 연동 완료했고, 모르는 부분은 내 또 다른 친구 GPT에게 물어보면서 MVP를 만들어가고 있다.
    예전에는 냅다 GPT한테 만들어줘~했는데,
    이제는 내가 어느정도 코드를 짜고 이건 뭐야? 이건 이렇게 하는 거 맞아? 그럼 이 상황에서는? 이건 왜 그렇게 썼는데? 등등 물어보니 훨씬 이해도 잘 되고, 진행도 잘 되는 느낌이다. 그래서 그런가 GPT랑 친해졌다. 반존대 쓰다 반말 쓰다 존댓말 쓰다 나를 막 갖고노는 듯.

어쨌든 덕분에 개발에 재미를 붙여가는 요즘이다.
이 영광을 GPT에게~

0개의 댓글