A Developing Developer
[스파르타코딩클럽] 웹개발의 봄, Spring - 3주차 본문
[수업 목표]
1. 페이지를 만들기 위한 HTML, CSS, Javascript를 익힌다.
2. 스프링을 이용해 API를 만들고 기능 확인하는 법을 손에 익힌다.
3. 타임라인 서비스를 완성한다.
01. [3주차] 이번 주 배울 것
- [코드스니펫] 타임라인 서비스 주소
http://spring.spartacodingclub.kr/timeline
- 서버 완성하기 - Memo API
- 2주차 때 배운 내용을 바탕으로 CRUD 기능을 가진 Memo API를 만듭니다.
- 키워드: RestController, Service, Repository, RequestDto
- HTML, CSS
- 웹 화면을 구성하는 HTML, CSS에 대해 배워봅니다.
- Javascript, jQuery
- 웹 화면을 움직이게 만들어주는 Javascript의 기초를 배웁니다.
- jQuery 를 이용하여 화면을 숨기고, 나타내는 방법을 익혀봅니다.
- 클라이언트 완성하기
- HTML, CSS, Javascript 를 바탕으로 클라이언트를 완성하고, 서버와 연결합니다.
- 완성된 페이지를 로컬에서 확인합니다.
02. [3주차] 프로젝트 만들고 API 설계하기
잠깐, 전체 그림을 다시 볼까요?
- Controller - Service - Repository 3 계층이 존재한다는 것, 기억하시죠?
- 우리는 안에서 바깥으로, 즉 Repository 쪽부터 Service, Controller 방향으로 만들어나갈 거예요.
- 이번 시간에는 Repository부터 만들어보겠습니다.
- 프로젝트 새로 만들기
1. 인텔리제이를 실행합니다.
2. New Project를 클릭합니다.
3. 왼쪽 메뉴에서 "Spring Initializr"를 클릭하고 "Next"를 클릭합니다.
4. [중요] 꼭 다음 사항을 확인해주세요.
- Group: com.sparta
- Artifact: week03
- Type: Gradle
- Language: Java Java Version: 8
특히 Type, Language, Java version 중 하나라도 다르면 정상적으로 실행이 되지 않습니다.
꼭 정상 입력 확인해주세요!
5. 검색창을 클릭하고, 다음을 차례대로 검색한 뒤 엔터를 눌러주세요.
검색이 끝난 뒤 아래 캡처의 우측과 같이 5개의 요소가 포함되어있으면 완료된 것입니다.
- Lombok
- Spring Web
- Spring Data JPA
- H2 Database
- MySQL Driver
6. Finish를 클릭합니다.
7. 잠시 기다리면, 아래 화면이 완성될 것입니다.
- API 설계하기(CRUD)
03. [3주 차] Repository 만들기
- Memo 클래스 만들기
- 메모는 1) 익명의 작성자 이름(username), 2) 메모 내용(contents)으로 이루어져 있습니다.
- domain 패키지를 만듭니다.
[코드스니펫] Memo.java
@NoArgsConstructor // 기본 생성자를 만듭니다.
@Getter @Entity // 테이블과 연계됨을 스프링에게 알려줍니다.
public class Memo extends Timestamped { // 생성, 수정 시간을 자동으로 만들어줍니다.
@GeneratedValue(strategy = GenerationType.AUTO)
@Id
private Long id;
@Column(nullable = false)
private String username;
@Column(nullable = false)
private String contents;
public Memo(String username, String contents) {
this.username = username;
this.contents = contents;
}
public Memo(MemoRequestDto requestDto) {
this.username = requestDto.getUsername();
this.contents = requestDto.getContents();
}
}
[코드스니펫] Timestamped.java
@MappedSuperclass // Entity가 자동으로 칼럼으로 인식합니다.
@EntityListeners(AuditingEntityListener.class) // 생성/변경 시간을 자동으로 업데이트합니다.
public class Timestamped {
@CreatedDate
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime modifiedAt;
}
- MemoRepository 인터페이스 만들기
ID가 Long 타입입니다. Repository는 어떻게 생겼을까요?
[코드스니펫] MemoRepository.java
public interface MemoRepository extends JpaRepository<Memo, Long> {
List<Memo> findAllByOrderByModifiedAtDesc();
}
[코드스니펫] JPA 공식 홈페이지 살펴보기
https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods
- 연습 퀴즈 - MemoRequestDto 클래스 만들기
- Memo.java에 뜨는 에러를 해결하려면 MemoRequestDto.java를 만들어야 합니다.
- Memo 클래스의 코드를 바탕으로 MemoRequestDto.java를 만들어보세요.
- 정답
@Getter
public class MemoRequestDto {
private String username;
private String contents;
}
04. [3주 차] Service 만들기
- 전체 그림 다시 보기
- Controller - Service - Repository 3 계층이 존재한다는 것, 기억하시죠?
- 이번 시간에는 Controller 계층을 만들어보겠습니다.
- API 완성하기
- MemoController.java 만들기
1. src > main > java > com.sparta.week03에 controller 패키지 만들기
2. [코드스니펫] MemoController.java 시작
@RequiredArgsConstructor//lombok, 반드시 사용해야 하니까 넣어줘
@RestController//JSON
public class MemoController {
private final MemoRepository memoRepository;
private final MemoService memoService;
}
- Create
[코드스니펫] MemoController.java > create
@PostMapping("/api/memos")
public Memo createMemo(@RequestBody MemoRequestDto requestDto) {
Memo memo = new Memo(requestDto);
return memoRepository.save(memo);
}
- Read
[코드스니펫] MemoController.java > read
@GetMapping("/api/memos")
public List getMemos() {
return memoRepository.findAllByOrderByModifiedAtDesc();
}
- Delete
[코드스니펫] MemoController.java > delete
@DeleteMapping("/api/memos/{id}")
public Long deleteMemo(@PathVariable Long id) {
memoRepository.deleteById(id); return id;
}
- ARC로 기능 확인하기
(조회) 빈 목록 반환
- Method: GET
- URL: http://localhost:8080/api/memos
(생성) 신규 메모 생성
- Method: POST
- URL: http://localhost:8080/api/memos
- Headers: Content-Type - application/json
[코드스니펫] ARC 신규 메모 생성 Body
{
"username": "avfnek2",
"contents": "첫 번째 메모"
}
(조회) 신규 메모 조회
- Method: GET
- URL: http://localhost:8080/api/memos
(삭제) 신규 메모 삭제
- Method: DELETE
- URL: http://localhost:8080/api/memos
(조회) 빈 목록 반환
- Method: GET
- URL: http://localhost:8080/api/memos/1
- 연습 퀴즈 - Update API 만들어보기
- 메모의 정보를 받아 DB의 데이터를 변경하는 메서드를 만들어보세요.
힌트) Create와 유사합니다.
- 정답
@PutMapping("/api/memos/{id}")
public Long updateMemo(@PathVariable Long id, @RequestBody MemoRequestDto requestDto) {
memoService.update(id, requestDto);
return id;
}
06. [3주 차] HTML, CSS 기초
- HTML, CSS, Javascript의 구분
HTML은 뼈대고, CSS는 꾸며주는 녀석입니다.
- HTML의 특징
- 여는 태그, 닫는 태그가 쌍으로 존재합니다.
- 교차가 불가능합니다.
(O) <h1><span>타이틀</span>입니다.</h1>
(X) <span><h1>타이틀</span>입니다.</h1>
- head, body 태그로 구분됩니다.
- head 태그는 CSS, Javascript 코드를 포함하고
- body 태그는 뼈대 전체를 포함합니다.
- 대표적인 HTML 태그들
- h1~h6
→ headline의 약자, 신문 제목 같은 녀석이에요.
- div
→ divison, 나누는 녀석이에요. 투명 비닐봉투!
- p
→ paragraph, 신문 기사 단락과 같은 텍스트 내용을 담습니다.
- ul, ol, li
→ (un)ordered list, list에 해당합니다. bullet point.
- span
→ 글을 중간중간 잘라내서 색을 입혀준다든지 할 때 사용합니다.
- table, th, tr, td
→ 표 입니다! 엑셀 같은 표를 그릴 때 사용합니다.
- img
→ 이미지를 나타낼 때 사용합니다.
그 외에도 무수히 많습니다! 더 공부하고 싶다면?
[코드스니펫] 코드카데미 HTML
https://www.codecademy.com/learn/learn-html
[코드스니펫] 생활코딩 HTML
https://opentutorials.org/course/2039
- CSS의 기초
- 문법
- head > style 태그 안에 작성합니다.
- 세미콜론(;)으로 마무리합니다.
.wrap {
width: 538px;
margin: 10px auto;
}
#contents {
width: 538px;
}
.area-write {
position: relative;
width: 538px;
}
- 선택자(id, class)
- 꾸미려면 가리켜야 하겠죠? 가리키는 방법은 두 가지가 있습니다.
- id: HTML 파일을 통틀어 단 하나만 존재합니다. #으로 표시합니다. (#contents)
- class: 중복 적용이 가능합니다. .으로 표시합니다. (.area-write)
07. [3주차] Javascript 기초 - 1
- Javascript 란?
- 브라우저를 살아 숨쉬게 만드는 친구입니다.
- 클릭, 마우스 오버 시 색 변화, 숨기기, 나타내기, 등등 수많은 일을 할 수 있답니다.
- 크롬 개발자 도구
- Javascript 공부, 아니 웹서비스 개발을 하는데 필수적인 녀석입니다.
- F12 키를 누르면 개발자 도구가 뜹니다! console 탭을 눌러볼게요.
- Javascript 기초 문법
- 변수
[코드스니펫] 자바스크립트 변수
let a = 3; // 변수를 처음 선언할 때 let을 써줍니다. 자료형은 써주지 않아도 되어요.
let b = 2;
console.log(a + b); // System.out.println()과 같은 녀석입니다.
b = 7;
console.log(a + b);
- 자료형 (문자, 숫자, boolean, 리스트, 딕셔너리)
[코드스니펫] 자바스크립트 문자, 숫자
let name = 'bknam';
let course = "웹개발의 봄 Spring" // 자바와 다르게 홑/쌍따옴표 상관없습니다.
let num = 10;
console.log(num + name); // 문자 + 숫자 하면 둘 모두를 문자로 묶습니다.
[코드스니펫] 자바스크립트 boolean
let age1 = 18;
let age2 = 20;
let isAdult = age1 > 19;
console.log(isAdult); // false
isAdult = age2 > 19; console.log(isAdult); // true
[코드스니펫] 자바스크립트 리스트
let fruits = ['사과', '딸기', '수박']; // List 보다 편하게 사용할 수 있습니다.
console.log(fruits[0]);
console.log(fruits[1]);
console.log(fruits[2]);
[코드스니펫] 자바스크립트 딕셔너리
let course = {
'title': '웹개발의 봄, Spring',
'tutor': '남병관'
};
console.log(course);
- 반복문
[코드스니펫] 자바스크립트 반복문
let fruits = ['사과', '딸기', '수박']; // List 보다 편하게 사용할 수 있습니다.
for (let i=0; i < fruits.length; i++) {
let fruit = fruits[i];
console.log(fruit == '수박');
}
- 함수
[코드스니펫] 자바스크립트 함수
function sample() {
alert('얼럿!');
}
- 백틱
[코드스니펫] 자바스크립트 백틱 연습
let name = '내 이름';
let text = `${name}님의 스프링 5주 완주를 축하합니다!`;
console.log(text);
연습 퀴즈 - 과일 개수 세기
- Javascript 배열 안에서 과일이 몇 개인지 세는 함수를 만들어보겠습니다.
다음 실행 결과를 만들 수 있으면 됩니다.
- let count = countFruit('감');
console.log(count); // 배열에 들어있는 감의 개수 인쇄
- 정답
let fruits = ['사과', '딸기', '수박', '감', '배', '딸기', '감'];
function countFruit(name) {
let result = 0;
for (let i=0; i < fruits.length; i++) {
let fruit = fruits[i];
if (fruit == name) {
result += 1;
}
}
return result;
}
let count = countFruit('감');
console.log(count); // 배열에 들어있는 감의 개수 인쇄
09. [3주차] jQuery 기초 - 1
- jQuery 란?
- jQuery는, 미리 작성된 자바스크립트 함수 모음집입니다.
- 되게 많이들 쓰는 HTML, CSS 조작 함수를 미리 만들어서 제공해주는 것이죠!
- 우리는 다 스스로 만들 필요 없이 사용법만 알면 됩니다.
- https://www.w3schools.com/jquery/jquery_get_started.asp
[코드스니펫] jQuery 임포트 (head 태그 사이에!)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
- jQuery 사용하는 법
$ 로 시작하고, 괄호 안에 선택자로 대상을 적으면 됩니다.
$('#contents').hide();
- 연습 장소로 들어가보기
- 개발자 도구 > 콘솔 에서 jQuery 를 사용하려면 해당 웹사이트에 이미 임포트 되어 있어야 합니다.
[코드스니펫] jQuery 놀이터 들어가기
- 숨기기 / 나타내기
[코드스니펫] HTML 나타내기
$('#post-box').show();
[코드스니펫] HTML 숨기기
$('#post-box').hide();
10. [3주차] jQuery 기초 - 2
- input 값 가져오기, 넣기
[코드스니펫] input 값 가져오기
$('#post-url').val();
[코드스니펫] input 값 넣기
$('#post-url').val('new text');
- HTML 없애기, 추가하기
[코드스니펫] HTML 없애기
$('#cards-box').empty();
[코드스니펫] HTML 추가하기
11. [3주차] 클라이언트 설계하기\
- 필요한 기능 살펴보기
1. 접속하자마자 메모 전체 목록 조회하기
a. GET API 사용해서 메모 목록 불러오기
b. 메모 마다 HTML 만들고 붙이기
2. 메모 생성하기
a. 사용자가 입력한 메모 내용 확인하기
b. POST API 사용해서 메모 신규 생성하기
c. 화면 새로고침하여 업데이트 된 메모 목록 확인하기
3. 메모 변경하기
a. 사용자가 클릭한 메모가 어떤 것인지 확인
b. 변경한 메모 내용 확인
c. PUT API 사용해서 메모 내용 변경하기
d. 화면 새로고침하여 업데이트 된 메모 목록 확인하기
4. 메모 삭제하기
a. 사용자가 클릭한 메모가 어떤 것인지 확인
b. DELETE API 사용해서 메모 삭제하기
c. 화면 새로고침하여 업데이트 된 메모 목록 확인하기
- 시작코드
src > main > resources > static 에 images 폴더를 만들고, 아래 이미지 4장을 넣어주세요!
(브라우저에 붙여넣고 엔터를 누르시면 이미지 다운로드가 됩니다.)
[코드스니펫] delete.png 다운로드
https://s3.ap-northeast-2.amazonaws.com/materials.spartacodingclub.kr/spring/week03/delete.png
[코드스니펫] done.png 다운로드
https://s3.ap-northeast-2.amazonaws.com/materials.spartacodingclub.kr/spring/week03/done.png
[코드스니펫] edit.png 다운로드
https://s3.ap-northeast-2.amazonaws.com/materials.spartacodingclub.kr/spring/week03/edit.png
[코드스니펫] send.png 다운로드
https://s3.ap-northeast-2.amazonaws.com/materials.spartacodingclub.kr/spring/week03/send.png
12. [3주차] 메모 생성하기 - writePost 함수
- 개발 스펙 확인
1. 사용자가 입력한 메모 내용 확인하기
2. POST API 사용해서 메모 신규 생성하기
3. 화면 새로고침하여 업데이트 된 메모 목록 확인하기
[코드스니펫] 사용자가 입력한 메모 내용 확인하기
let contents = $('#contents').val();
[코드스니펫] 작성 내용 확인하기
if (isValidContents(contents) == false) {
return;
}
[코드스니펫] 랜덤한 username 만들기
let username = genRandomName(10);
[코드스니펫] 전달할 data 를 JSON으로 만들기
let data = {'username': username, 'contents': contents};
[코드스니펫] POST API 사용해서 메모 신규 생성하기
! 잠깐, JSON.stringify 란? JSON을 문자열로 만들어주는 것입니다!
$.ajax({
type: "POST",
url: "/api/memos",
contentType: "application/json", // JSON 형식으로 전달함을 알리기
data: JSON.stringify(data),
success: function (response) {
alert('메시지가 성공적으로 작성되었습니다.');
window.location.reload();
}
});
[코드스니펫] writePost 함수 완성
// 메모를 생성합니다.
function writePost() {
// 1. 작성한 메모를 불러옵니다.
let contents = $('#contents').val();
// 2. 작성한 메모가 올바른지 isValidContents 함수를 통해 확인합니다.
if (isValidContents(contents) == false) {
return;
}
// 3. genRandomName 함수를 통해 익명의 username을 만듭니다.
let username = genRandomName(10);
// 4. 전달할 data JSON으로 만듭니다.
let data = {'username': username, 'contents': contents};
// 5. POST /api/memos 에 data를 전달합니다.
$.ajax({
type: "POST",
url: "/api/memos",
contentType: "application/json",
data: JSON.stringify(data),
success: function (response) {
alert('메시지가 성공적으로 작성되었습니다.');
window.location.reload();
}
});
}
13. [3주차] 메모 조회하기 - getMessages 함수 - 1
- 개발 스펙 확인
1. 기존 메모 제거하기
2. GET API 사용해서 메모 목록 불러오기
3. 메모마다 HTML 만들고 붙이는 함수 만들기
- 메모 조회하기
아래의 붉은 상자 영역이 div#cards-box 입니다. 메모 목록을 담는 div 입니다.
이번 작업은 getMessages(), addHTML() 함수를 다루는 것입니다.
[코드스니펫] 기존 메모 제거하기
$('#cards-box').empty();
[코드스니펫] GET API 사용해서 메모 목록 불러오기
$.ajax({
type: 'GET',
url: '/api/memos',
success: function (response) {
console.log(response);
}
))
14. [3주차] 메모 조회하기 - getMessages 함수 - 2
[코드스니펫] 메모 마다 HTML 만들고 붙이는 함수 만들기
- Timestamped, Week03Application 수정하기
- 뭔가 이상하지 않으셨나요? 왜 created_at, modified_at 데이터는 안 오는 것일까요?
- 바로 Getter 가 없기 때문입니다. 참 놓치기 쉽죠?
- 거기에, 스프링에게 Auditing 기능을 사용하고 있다고 알려주어야 해요!
- 이렇게 중간중간 어노테이션을 빼먹으면 작동이 의도대로 안될 때가 많답니다.
[코드스니펫] 반복문 안에서 addHTML 호출
[코드스니펫] getMessages, addHTML 완성
15. [3주차] 메모 변경하기 - submitEdit 함수
- 개발 스펙 확인
1. 작성 대상 메모의 username과 contents 를 확인
2. 작성한 메모가 올바른지 확인
3. 전달할 data 를 JSON으로 바꾸기
4. PUT /api/memos/{id} 에 data를 전달
[코드스니펫] addHtml 리뷰
[코드스니펫] 작성 대상 메모의 username과 contents 를 확인
let username = $(`#${id}-username`).text().trim();
let contents = $(`#${id}-textarea`).val().trim();
[코드스니펫] 작성한 메모가 올바른지 확인
if (isValidContents(contents) == false) {
return;
}
[코드스니펫] 전달할 data 를 JSON으로 바꾸기
let data = {'username': username, 'contents': contents};
[코드스니펫] PUT /api/memos/{id} 에 data를 전달
$.ajax({
type: "PUT",
url: `/api/memos/${id}`,
contentType: "application/json",
data: JSON.stringify(data),
success: function (response) {
alert('메시지 변경에 성공하였습니다.');
window.location.reload();
}
});
[코드스니펫] submitEdit 함수 완성
// 메모를 수정합니다.
function submitEdit(id) {
// 1. 작성 대상 메모의 username과 contents 를 확인합니다.
let username = $(`#${id}-username`).text().trim();
let contents = $(`#${id}-textarea`).val().trim();
// 2. 작성한 메모가 올바른지 isValidContents 함수를 통해 확인합니다.
if (isValidContents(contents) == false) {
return;
}
// 3. 전달할 data JSON으로 만듭니다.
let data = {'username': username, 'contents': contents};
// 4. PUT /api/memos/{id} 에 data를 전달합니다.
$.ajax({
type: "PUT",
url: `/api/memos/${id}`,
contentType: "application/json",
data: JSON.stringify(data),
success: function (response) {
alert('메시지 변경에 성공하였습니다.');
window.location.reload();
}
});
}
16. [3주차] 메모 삭제하기 - deleteOne 함수
- 개발 스펙 확인
1. DELETE API 사용해서 메모 삭제하기
[코드스니펫] DELETE API 사용해서 메모 삭제하기
function deleteOne(id) {
$.ajax({
type: "DELETE",
url: `/api/memos/${id}`,
success: function (response) {
alert('메시지 삭제에 성공하였습니다.');
window.location.reload();
}
})
}
[코드스니펫] 클라이언트 완성 코드
https://github.com/H-JJOO/week03/blob/master/src/main/resources/static/index.html
17. [3주차] 끝 & 숙제설명 잠깐 복습
드디어! 우리가 End to End 로, 처음부터 끝까지, 를 만들어 보았습니다.
다소 빠르고 힘겹게 느껴지신다구요?
제대로 공부하고 계시다는 증거입니다.
약간의 속도감이 우리의 실력을 한 차원 끌어올리고 있어요!
4주차 수업 <나만의 셀렉샵>을 위해, 이번 주 잘 소화해주실거죠?
- Rest API의 CRUD 전체 프로세스를, 다시 한 번 복습했습니다.
- HTML, CSS, Javascript, jQuery를 통해 보이는 화면을 만들고 조작하는 방법에 대해 배웠습니다.
- API를 먼저 설계하고, 그에 따라 클라이언트 코드 작성하는 프로세스를 익혔습니다.
=================================================================================
출처 : [스파르타코딩클럽] 웹개발의 봄, Spring(강의자료)
=================================================================================
3주차는 조금 여유있게 끝냈다고 생각했는데. 개발일지 마무리가 결국 토요일이다...
4주차에 본격적으로 프로젝트를 만들기 시작하는 강의를 한다고하는데 남은 주말간에 공부를 더 해야겠다.
3주차 동안에 수업외로 '내일배움캠프 4기' 에 지원하는 작업을하였다.
1차 합격 후 2차 영상 셀프 인터뷰까지 제출한 상태이고 다음주면 결과가 나올 듯 하다.
행해99 와 비슷하거나 같은 커리큘럼 같은데, 9 to 9 (AP09:00 ~ PM09:00) 12시간 계획을 22.10.31 ~ 23.03.08 5개월 동안 코딩공부를 한다니... 일단 지원은했지만 부담되고 걱정되는건 어쩔수 없는것 같다.
하지만 최종 선발이되고 하루하루 계획대로 진행한다면 5개월 뒤에는 1인분 이상 가능한 개발자가 될 것이라는 확신을 가지고 끝까지 완주해보고싶다.
(일단 뽑아줘요~ 살아남아 볼테니...)
'웹개발의 봄, Spring 81기' 카테고리의 다른 글
[스파르타코딩클럽] 웹개발의 봄, Spring - 5주차 (1) | 2022.10.05 |
---|---|
[스파르타코딩클럽] 웹개발의 봄, Spring - 4주차 (1) | 2022.10.03 |
[스파르타코딩클럽] 웹개발의 봄, Spring - 2주차 (1) | 2022.09.18 |
[스파르타코딩클럽] 웹개발의 봄, Spring - 1주차 (2) | 2022.09.11 |