SpringBoot와 관련하여 매니저님에게 강의를 추천받아 해당 강의를 듣고 정리했습니다.
이 강의 내용과 강사님의 자료를 종합해서 보니 어느정도 SpringBoot의 구조와 흐름을 알게된 것 같습니다.
MVC와 TemplateEngine
○ Model
● Data와 비즈니스 로직 담당
● DB와의 상호작용(서비스 계층을 통해 데이터 처리 및 전송)
○ View
● 보여지는 UI를 담당
● Model에 전달받은 데이터를 화면에 출력
● Html, Jsp, Thymeleat | Json과 같은 형식으로 사용자에게 전달
○ Controller
● 사용자로부터의 요청 처리 및 모델과 뷰를 연결하는 역할
● 요청을 받아 모델에서 데이터를 가져오거나 변경
● 결과를 뷰에 전달
* thymeleaf를 쓸 때 해당 html에서 오른쪽 마우스를 누르고 Copy path 한 내용을 웹에 치면 바로 나옴
@ResponseBody : 데이터를 Body부분에 바로 넣어주는 어노테이션
API 방식 => json 형태로 넘어가게 됨
HttpMessage Converter가 문자열이 오게되면 StringConverter로 String을 반환
if 객체를 받으면 JsonConverter를 실행하여 객체를 그대로 넘겨줌
@GetMapping("hello-api")
@ResponseBody
public Hello helloApi(@RequestParam("name") String name){
Hello hello = new Hello();
hello.setName(name);
// 객체를 그대로 넘겨줌
return hello;
}
static class Hello {
private String name;
// Getter Setter JavaBean 표준 방식으로 property 접근 방식
// private인 String name을 사용 하기 위함
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
}
회원관리 예제(백엔드 개발)
0. 비즈니스 요구사항
● 데이터 : 회원 ID, 이름
● 기능 : 회원등록 및 조회
● 데이터 저장소는 선정하지 않음
1. 회원 도메인, 리포지토리 생성
2. 회원 리포지토리 테스트 케이스 작성
3. 회원 서비스 개발
4. 회원 서비스 테스트
일반적인 web Application 계층 구조
● Controller : web MVC 컨트롤러 역할
● Service : 핵심 비즈니스 로직 구현
● Repository : DB 접근, 도메인 객체를 DB에 저장하고 관리
● Domain : 비즈니스 도메인 객체 e.g. 회원, 주문, 쿠폰 등등 주로 DB에 저장하고 관리
클래스의 의존관계 : 현재 DB를 선정하지 않아서 Interface로 구현 => 클래스를 변경 가능하도록 설계
Getter/Setter extension 설치 및 자동 생성
: Getter/Setter 만들고자 하는 변수를 드래그 → F1키 → get 해서 generate gettter/setter하면 자동 생성
MemoryMemberRepository implements MemberRepository 로 선언하고
MemoryMemberRepository에서 빨간 줄 Quick Fix해서 add All implements → 추가해서 수정
// MemoryMemberRepository.java
package hello.hello_spring.repository;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.springframework.stereotype.Repository;
import hello.hello_spring.domain.Member;
@Repository
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) {
// Optional.ofNullable 하면 Null이어도 반환 가능하게 해줌
return Optional.ofNullable(store.get(id));
}
@Override
public Optional<Member> findByname(String name) {
return store.values().stream()
.filter(member -> member.getName().equals(name))
.findAny();
}
@Override
public List<Member> findAll() {
return new ArrayList<>(store.values());
}
//테스트 할 때 리포지토리 초기화해주는 함수
public void clearStore(){
store.clear();
}
}
Optional.ofNullable 하면 Null이어도 반환 가능하게 해줌 → return Optional.ofNullable(store.get(id));
src/test/java 하위폴더에 TestCase 생성
testCase도 javaproject와 똑같이 작성해주기
@AfterEach를 적어주지 않으면 findAll() 메소드가 먼저 실행이됨
그래서 findByName 부분에서 에러가 발생한다.
So, Test하고 나면 repository를 계속 지워줘야함
그래서 @AfterEach로 끝난 후 repository.clearStore() 함수를 실행해줌
src\main\java\hello\hello_spring\repository\MemoryMemberRepository.java 의 public void clearStore() 메소드
//테스트 할 때 리포지토리 초기화해주는 함수
public void clearStore(){
store.clear();
}
테스트 코드
test\java\hello\hello_spring\repository\MemoryMemberRepositoryTest.java
package hello.hello_spring.repository;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import hello.hello_spring.domain.Member;
class MemoryMemberRepositoryTest{
MemoryMemberRepository repository = new MemoryMemberRepository();
@AfterEach
public void afterEach(){
repository.clearStore();
}
@Test
public void save(){
Member member = new Member();
member.setName("spring");
repository.save(member);
Member result = repository.findById(member.getId()).get();
//import 할 때 스태틱 안 쓰면 Assertions 앞에 써줘야함
// Assertions.assertThat(member).isEqualTo(result);
assertThat(member).isEqualTo(result);
}
@Test
public void findByName(){
Member member1 = new Member();
member1.setName("spring1");
repository.save(member1);
Member member2 = new Member();
member2.setName("spring2");
repository.save(member2);
Member result = repository.findByname("spring1").get();
assertThat(result).isEqualTo(member1);
}
@Test
public void findAll(){
Member member1 = new Member();
member1.setName("spring1");
repository.save(member1);
Member member2 = new Member();
member2.setName("spring2");
repository.save(member2);
List<Member> result = repository.findAll();
assertThat(result.size()).isEqualTo(2);
}
}
src\test\java\hello\hello_spring\service\MemberServiceTest.java
package hello.hello_spring.service;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.jupiter.api.AfterEach;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import hello.hello_spring.domain.Member;
import hello.hello_spring.repository.MemoryMemberRepository;
public class MemberServiceTest {
MemberService memberService;
MemoryMemberRepository memberRepository;
@BeforeEach
public void beforeEach(){
memberRepository = new MemoryMemberRepository();
memberService = new MemberService((memberRepository));
}
@AfterEach
public void afterEach(){
memberRepository.clearStore();
}
@Test
void testFindMembers() {
//given
Member member = new Member();
member.setName("hello");
//when
Long saveId = memberService.join(member);
//then
Member findMember = memberService.findOne(saveId).get();
assertThat(member.getName()).isEqualTo(findMember.getName());
}
@Test
public void except_duplication(){
//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("이미 존재하는 회원");
/* try-catch 방법
try {
memberService.join(member2);
fail();
} catch (IllegalStateException e) {
Assertions.assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원");
}
*/
//then
}
@Test
void testFindOne() {
}
@Test
void testJoin() {
}
}
src\test\java\hello\hello_spring\HelloSpringApplicationTests.java
package hello.hello_spring;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class HelloSpringApplicationTests {
@Test
void contextLoads() {
}
}
Service
: VSCode Quickfix로 Optional import할 때 java.util.Optional로 해줘야함
자동으로 해주면 다른 패키지의 걸 불러와서 오류 발생
* test 자동 생성 : 코드 모두 선택 → 오른쪽 키 → Go to test → generatetest → 만들고 함수 선택 → 생성
* test 코드 작성 팁 : given → when → then
- given : 어떠한 상황이 주어짐(데이터를 확인)
- when : 실행하였을 때(검증 로직을 확인)
- then : 나오는 결과
* private final MemberRepository memberRepository; 오른쪽 키 → add parameter .. constructure ...
→ hello.hello_spring.repository 지우고 아래와 같이 적어주기
src\main\java\hello\hello_spring\service\MemberService.java
package hello.hello_spring.service;
import java.util.List;
import java.util.Optional;
import hello.hello_spring.domain.Member;
import hello.hello_spring.repository.MemberRepository;
public class MemberService {
private final MemberRepository memberRepository;
// 같은 repository를 쓰기 위해 외부에서 넣어주기
// @Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
/*
* 회원가입
*/
public Long join(Member member){
validateDuplicateMember(member);
memberRepository.save(member);
return member.getId();
}
private void validateDuplicateMember(Member member){
// 중복 이름 불가
// Optional <Member> result = memberRepository.findByname(member.getName());
// result.ifPresent(m ->{
// throw new IllegalAccessException("이미 존재하는 회원");
// });
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);
}
}
src\main\java\hello\hello_spring\repository\MemberRepository.java
package hello.hello_spring.repository;
import java.util.List;
import java.util.Optional;
import hello.hello_spring.domain.Member;
public interface MemberRepository {
Member save(Member member);
Optional<Member> findById(Long id);
Optional<Member> findByname(String name);
List<Member> findAll();
}
스프링 빈과 의존관계
○ 스프링 빈을 등록하고 의존관계 설정하기
● 회원 컨트롤러가 회원서비스와 회원 리포지토리를 사용할 수 있도록 의존관계 설정하는 법
- @Controller 어노테이션 → Spring이 프로젝트를 만들 때 Controller 컨테이너를 생성해서 관리하게 됨
- @Autowired 어노테이션 → 생성된 Spring 컨테이너에 연결을 해줌
- 불러오고자하는(MemberService) 가장 위에 @Service라고 어노테이션을 달아줌
// service/MemberService.java
package hello.hello_spring.service;
import java.util.List;
import java.util.Optional;
import hello.hello_spring.domain.Member;
import hello.hello_spring.repository.MemberRepository;
public class MemberService {
private final MemberRepository memberRepository;
// 같은 repository를 쓰기 위해 외부에서 넣어주기
// @Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
/*
* 회원가입
*/
public Long join(Member member){
validateDuplicateMember(member);
memberRepository.save(member);
return member.getId();
}
private void validateDuplicateMember(Member member){
// 중복 이름 불가
// Optional <Member> result = memberRepository.findByname(member.getName());
// result.ifPresent(m ->{
// throw new IllegalAccessException("이미 존재하는 회원");
// });
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);
}
}
- 구현한 MemoryMemberRepository 위에 @Repository 어노테이션 적어주기
// Repository/MemoryMemberRepository.java
package hello.hello_spring.repository;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.springframework.stereotype.Repository;
import hello.hello_spring.domain.Member;
@Repository
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) {
// Optional.ofNullable 하면 Null이어도 반환 가능하게 해줌
return Optional.ofNullable(store.get(id));
}
@Override
public Optional<Member> findByname(String name) {
return store.values().stream()
.filter(member -> member.getName().equals(name))
.findAny();
}
@Override
public List<Member> findAll() {
return new ArrayList<>(store.values());
}
//테스트 할 때 리포지토리 초기화해주는 함수
public void clearStore(){
store.clear();
}
}
=> Spring이 각각 Service와 Repository라고 인식하고 다 가져와서 필요할 때 사용할 수 있게 해줌
- 파일 구조(Project Tree를 통해 작성)
```
hello-spring
├─ .vscode
│ └─ settings.json
└─ hello-spring
├─ .gradle
│ ├─ 8.10
│ │ ├─ checksums
│ │ │ ├─ checksums.lock
│ │ │ ├─ md5-checksums.bin
│ │ │ └─ sha1-checksums.bin
│ │ ├─ dependencies-accessors
│ │ │ └─ gc.properties
│ │ ├─ executionHistory
│ │ │ ├─ executionHistory.bin
│ │ │ └─ executionHistory.lock
│ │ ├─ expanded
│ │ ├─ fileChanges
│ │ │ └─ last-build.bin
│ │ ├─ fileHashes
│ │ │ ├─ fileHashes.bin
│ │ │ ├─ fileHashes.lock
│ │ │ └─ resourceHashesCache.bin
│ │ ├─ gc.properties
│ │ └─ vcsMetadata
│ ├─ buildOutputCleanup
│ │ ├─ buildOutputCleanup.lock
│ │ ├─ cache.properties
│ │ └─ outputFiles.bin
│ ├─ file-system.probe
│ ├─ nb-cache
│ │ ├─ hello-spring-642919548
│ │ │ └─ project-info.ser
│ │ ├─ subprojects.ser
│ │ └─ trust
│ │ └─ B436318CAAF240F393235917B67B4926905B7D4B71FE40519F1555B6BBEDEDA3
│ └─ vcs-1
│ └─ gc.properties
├─ build
│ ├─ classes
│ │ └─ java
│ │ ├─ main
│ │ │ └─ hello
│ │ │ └─ hello_spring
│ │ │ ├─ controller
│ │ │ │ ├─ HelloController$Hello.class
│ │ │ │ ├─ HelloController.class
│ │ │ │ ├─ HomeController.class
│ │ │ │ ├─ MemberController.class
│ │ │ │ └─ MemberForm.class
│ │ │ ├─ domain
│ │ │ │ └─ Member.class
│ │ │ ├─ HelloSpringApplication.class
│ │ │ ├─ repository
│ │ │ │ ├─ MemberRepository.class
│ │ │ │ └─ MemoryMemberRepository.class
│ │ │ ├─ service
│ │ │ │ └─ MemberService.class
│ │ │ └─ SpringConfig.class
│ │ └─ test
│ │ └─ hello
│ │ └─ hello_spring
│ │ ├─ HelloSpringApplicationTests.class
│ │ ├─ repository
│ │ │ └─ MemoryMemberRepositoryTest.class
│ │ └─ service
│ │ └─ MemberServiceTest.class
│ ├─ generated
│ │ └─ sources
│ │ ├─ annotationProcessor
│ │ │ └─ java
│ │ │ ├─ main
│ │ │ └─ test
│ │ └─ headers
│ │ └─ java
│ │ ├─ main
│ │ └─ test
│ ├─ reports
│ │ └─ tests
│ │ └─ test
│ │ ├─ classes
│ │ │ └─ hello.hello_spring.service.MemberServiceTest.html
│ │ ├─ css
│ │ │ ├─ base-style.css
│ │ │ └─ style.css
│ │ ├─ index.html
│ │ ├─ js
│ │ │ └─ report.js
│ │ └─ packages
│ │ └─ hello.hello_spring.service.html
│ ├─ resources
│ │ ├─ main
│ │ │ ├─ application.properties
│ │ │ ├─ static
│ │ │ │ └─ index.html
│ │ │ └─ templates
│ │ │ ├─ hello-template.html
│ │ │ ├─ hello.html
│ │ │ ├─ home.html
│ │ │ └─ members
│ │ │ ├─ createMemberForm.html
│ │ │ └─ memberList.html
│ │ └─ test
│ ├─ test-results
│ │ └─ test
│ │ ├─ binary
│ │ │ ├─ output.bin
│ │ │ ├─ output.bin.idx
│ │ │ └─ results.bin
│ │ └─ TEST-hello.hello_spring.service.MemberServiceTest.xml
│ └─ tmp
│ ├─ assemble
│ ├─ bootBuildImage
│ ├─ bootJar
│ │ └─ MANIFEST.MF
│ ├─ bootRun
│ ├─ bootTestRun
│ ├─ build
│ ├─ buildDependents
│ ├─ buildEnvironment
│ ├─ buildNeeded
│ ├─ check
│ ├─ classes
│ ├─ clean
│ ├─ compileJava
│ │ ├─ compileTransaction
│ │ │ ├─ backup-dir
│ │ │ └─ stash-dir
│ │ │ └─ MemberController.class.uniqueId0
│ │ └─ previous-compilation-data.bin
│ ├─ compileTestJava
│ │ ├─ compileTransaction
│ │ │ ├─ backup-dir
│ │ │ └─ stash-dir
│ │ │ ├─ MemberServiceTest.class.uniqueId1
│ │ │ └─ MemoryMemberRepositoryTest.class.uniqueId0
│ │ └─ previous-compilation-data.bin
│ ├─ components
│ ├─ dependencies
│ ├─ dependencyInsight
│ ├─ dependencyManagement
│ ├─ dependentComponents
│ ├─ help
│ ├─ init
│ ├─ jar
│ │ └─ MANIFEST.MF
│ ├─ javadoc
│ ├─ javaToolchains
│ ├─ model
│ ├─ outgoingVariants
│ ├─ prepareKotlinBuildScriptModel
│ ├─ processResources
│ ├─ processTestResources
│ ├─ projects
│ ├─ properties
│ ├─ resolvableConfigurations
│ ├─ resolveMainClassName
│ ├─ resolveTestMainClassName
│ ├─ runSingle
│ ├─ tasks
│ ├─ test
│ ├─ testClasses
│ ├─ updateDaemonJvm
│ └─ wrapper
├─ build.gradle
├─ gradle
│ └─ wrapper
│ ├─ gradle-wrapper.jar
│ └─ gradle-wrapper.properties
├─ gradlew
├─ gradlew.bat
├─ HELP.md
├─ settings.gradle
└─ src
├─ main
│ ├─ java
│ │ └─ hello
│ │ └─ hello_spring
│ │ ├─ controller
│ │ │ ├─ HelloController.java
│ │ │ ├─ HomeController.java
│ │ │ ├─ MemberController.java
│ │ │ └─ MemberForm.java
│ │ ├─ domain
│ │ │ └─ Member.java
│ │ ├─ HelloSpringApplication.java
│ │ ├─ repository
│ │ │ ├─ MemberRepository.java
│ │ │ └─ MemoryMemberRepository.java
│ │ ├─ service
│ │ │ └─ MemberService.java
│ │ └─ SpringConfig.java
│ └─ resources
│ ├─ application.properties
│ ├─ static
│ │ └─ index.html
│ └─ templates
│ ├─ hello-template.html
│ ├─ hello.html
│ ├─ home.html
│ └─ members
│ ├─ createMemberForm.html
│ └─ memberList.html
└─ test
└─ java
└─ hello
└─ hello_spring
├─ HelloSpringApplicationTests.java
├─ repository
│ └─ MemoryMemberRepositoryTest.java
└─ service
└─ MemberServiceTest.java
```
스프링 빈을 등록하는 방법
1. 컴포넌트 스캔과 자동 의존관계 설정
2. 자바코드로 직접 스프링 빈 등록하기
컴포넌트 스캔과 자동 의존관계 설정
○ @Component : 스프링 빈에 자동 등록
○ @Controller : 컨트롤러가 스프링 빈으로 자동 등록된 이유도 컴포넌트 스캔 때문
○ @Component를 포함하는 다음 어노테이션도 스프링 빈으로 자동 등록
● @Controller, @Service, @Repository
○ Spring은 Spring 컨테이너에 Spring Bean을 등록할 때, 기본적으로 싱글톤으로 등록
(유일하게 하나만 등록해서 공유하는 것) So, 같은 스프링 빈이면 모두 같은 인스턴스
특별한 경우가 아니라면 대부분 싱글톤을 사용하는 것을 권장
자바 코드로 직접 스프링 빈 등록
○ 1번 방법으로 하였던 @Service, @Repository 지워주기
○ SpringConfig.java 파일 생성(경로 : HelloSpringApplication과 같은 디렉토리)
package hello.hello_spring;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import hello.hello_spring.repository.MemberRepository;
import hello.hello_spring.repository.MemoryMemberRepository;
import hello.hello_spring.service.MemberService;
@Configuration
public class SpringConfig {
@Bean
public MemberService memberService(){
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository(){
return new MemoryMemberRepository();
}
}
회원 가입 기능
● GetMapping에서 createMemberForm.html로 이동
● html에 있는 form action에 post방식으로 input이 있음
● input의 내용이 post방식으로 전달
● MemberController.java에 있는 @PostMapping으로 넘어감
● create 메소드가 호출되어 MemberForm.java에 있는 private String name에 값을 넣어줌
● private여서 setName으로 값을 넣어서 넘겨줌
● MemberController.java에 있는 member.setName(form.getName())으로 이름 값 꺼내기
● join으로 가입하고 페이지 redirect
회원 목록 보이기 기능
● 회원가입(home.html) 후 회원 목록 클릭
● Member에 저장된 데이터는 private
● getter를 통해 값을 불러옴
● thymeleaf 문법으로 memberList.html에서 사용된 코드가 Member에 저장된 모든 값들을 호출
코드
○ src\main\resources\templates\home.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div class="container">
<div>
<h1>Hello Spring</h1>
<p>회원 기능</p>
<p>
<a href="/members/new">회원 가입</a>
<a href="/members">회원 목록</a>
</p>
</div>
</div>
</body>
</html>
○ src\main\resources\templates\members\createMemberForm.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div class="container">
<form action="/members/new" method="post">
<div class="form-group">
<label for="name">이름</label>
<input type="text" id="name" name="name" placeholder="이름을 입력하세요">
</div>
<button type="submit">등록</button>
</form>
</div>
</body>
</html>
○ src\main\resources\templates\members\memberList.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<div class="container">
<div>
<table>
<thead>
<tr>
<th>#</th>
<th>이름</th>
</tr>
</thead>
<tbody>
<tr th:each="member : ${members}">
<td th:text="${member.id}"></td>
<td th:text="${member.name}"></td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>
○ src\main\java\hello\hello_spring\controller\MemberController.java
package hello.hello_spring.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import hello.hello_spring.domain.Member;
import hello.hello_spring.service.MemberService;
@Controller
public class MemberController {
private final MemberService memberService;
@Autowired
public MemberController(MemberService memberService){
this.memberService = memberService;
}
@GetMapping("/members/new")
public String createForm() {
return "members/createMemberForm";
}
@PostMapping("/members/new")
public String create(MemberForm form) {
Member member = new Member();
member.setName(form.getName());
memberService.join(member);
return "redirect:/";
}
@GetMapping("/members")
public String list(Model model) {
List<Member> members = memberService.findMembers();
model.addAttribute("members", members);
return "members/memberList";
}
}
○ src\main\java\hello\hello_spring\controller\MemberForm.java
package hello.hello_spring.controller;
public class MemberForm {
//createMemberForm에서 전달하는 name과 매칭이됨
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
현재 DB가 연결되어 있지 않는 상황이기에 DB를 연결해주는 강의를 정리할 예정
'Networks > SpringBoot' 카테고리의 다른 글
SK networks AI Camp - SpringBoot(2) (4) | 2024.09.06 |
---|---|
SK networks AI Camp - SpringBoot (5) | 2024.09.06 |