작업 7, 게시물 삭제 기능 추가(index 활용)
작업 8, 게시물 수정 기능 추가, 조회수 추가, 목록의 날짜 및 시각 노출 조절
작업 9, 게시글 테스트데이터 생성 구현
작업 10, ArrayList 내에서 특정 게시물을 찾는 메서드 구현, 중복 제거
작업 11, 게시글 검색 기능 추가(제목)
작업 12, 회원가입 구현중 LoginId 중복체크
작업 13, 회원가입 기능 구현, 비밀번호 확인 추가
작성한 글에 회원 정보가 있어야함(id)
-> 1. dowrite 메소드에 회원정보 넣기?
회원정보는 멤버컨트롤러에 잇음 -> 회원정보에서 id만 가져오기 -O
어떻게 넣어야할가 -> Article article에 같이 넣어야됨?
-> 멤버컨트롤러에서 저장된 회원정보를 컨트롤러에 어레이리스트를 만들어서 또담기?
로그인한 회원만 삭제 수정 가능 X
회원 id만 따로빼기
멤버컨트롤러에서 가져와야됨.
===
멤버컨트롤러에서 로그인한 id정보만 빼서 컨트롤러에 담았음
이제 아티클컨트롤러에서 그정보만 가져오면됨
-> 이 회원 id를 write 할때 담아야함 그래야 수정할때 거를 수 잇음
-> 중구 난방함.
** 비교대상을 잘 체크해야됨.
게시글 쓰기 완료
작성
목록
상세보기
수정
삭제
회원
회원가입
로그인
로그아웃
회원쪽 Service 구조 개선
내 정보 -> myPage
회원정보 수정 -> 선작업 : 비밀번호 입력
회원탈퇴 -> 선작업 : 비밀번호 입력
MVC
리팩토링
최적화
목록 보기(전체 데이터베이스 리스팅) : SHOW DATABASES;
mysql 데이터 베이스 선택 : USE mysql;
테이블 리스팅 : SHOW TABLES;
특정 테이블의 구조 : DESCRIBE func; or DESC func;
test 데이터 베이스 선택 : USE test;
테이블 리스팅 : SHOW TABLES;
기존에 a1 데이터베이스가 존재 한다면 삭제 :
DROP DATABASE a1; or DROP DATABASE IF EXISTS a1 ;
새 데이터베이스 (A1) 생성 : CREATE DATABASE a1;
데이터베이스 (a1) 선택 : USE a1;
데이터베이스 추가 되었는지 확인 : SHOW DATABASES;
게시물 테이블 article(title, body)을 만듭니다. :
CREATE TABLE article (
title VARCHAR(100),
body TEXT
);
잘 추가되었는지 확인, 리스팅과 구조까지 확인 :
SHOW TABLES;
DESC article;
데이터 하나 추가(title = 제목, body = 내용)
INSERT INTO article
SET title = '제목',
body = '내용';
데이터 조회(title 만)
SELECT title
FROM article;
데이터 조회(전부)
SELECT *
FROM article;
테이블 구조 수정(id 칼럼 추가, first) :
ALTER TABLE article ADD COLUMN id INT FIRST;
기존 데이터에 id값 추가(id = 1, id IS NULL)
UPDATE article
SET id = 1
WHERE id IS NULL;
기존 데이터 중 1개만 id를 2로 변경(LIMIT 1)
UPDATE article
SET id = 2
LIMIT 1;
날짜 칼럼 추가 => regDate DATETIME :
ALTER TABLE article ADD COLUMN regDate DATETIME AFTER id;
모든 행(row)의 id 값은 유니크 해야한다.(ADD PRIMARY KEY(id))
ALTER TABLE article ADD PRIMARY KEY(id);
id 칼럼에 auto_increment 를 건다.
ALTER TABLE article MODIFY COLUMN id INT NOT NULL AUTO_INCREMENT;
unsigned : 음수 불가, not null : null 불가, primary key(테이블 당 하나) : 중복불가, 및 not null ,Unique(제약 조건) : 중복 불가
한 시점당 한 행 추가
where (= if)
삭제하기전에
SELECT *
FROM article
WHERE id = 2; 로 확인해주면 안정적임 (꼭 하지 않아도 됨)
ADD PRIMARY KEY -> 중복금지
왼쪽 테이블에서 F6 상세보기
속성을 추가할 때, 전에 추가했던 부분 전부를 가져와서 그 뒤에 새로운 속성을 넣고 추가
(중복 걱정 안해도됨)
에러가 뜰때는 속성들의 위치를 바꿔본다
보통 AUTO_INCREMENT가 맨 뒤로 가야됨
데이터 조회는 SELECT 로 시작
조건문에서 아니다는 != or <> 로 쓸 수 있음
SELECT CONCAT('제목' , ' 1'); -> 제목 1 로 나옴
SELECT RAND(); -> 0~1 사이 랜덤 숫자
while (rs.next()) { <- 자바에서 SELECT 할 때 꼭 써야되는 것
작업 8, 게시물 리스팅 시 데이터를 DB로부터 가져오기
작업 9, 게시글 수정 기능 구현(존재 유무 체크x)
작업 10, App 생성, 각 기능 내부의 Connection 을 명령어 입력할 때 마다로 변경
만약 오류가 났으면 F6을 누르면 한번 더 진행하여 에러 메세지를 자세히 보여준다. -> 문제점을 찾을 때 유용
작업 12, 게시물 삭제, 상세보기, 없는 글 처리, 날짜 형식
INNER JOIN을 쓰는 이유 : 다른 곳에서 그 내용을 잘 모를 수 있기 때문에
-> 어떤 특정 조건을 만족할때만 써야됨
사장님께서 부서번호가 아니라 부서명을 알고 싶어하신다.
그래서 dept 테이블 조회법을 알려드리고 혼이 났다.
SELECT *
FROM dept
where id = 1;
사장님께 드릴 인명록을 생성(v2, 부서명 포함, ON 없이)
이상한 데이터가 생성되어서 혼남
SELECT emp.*, dept.name AS 부서명
FROM emp
inner join dept;
사장님께 드릴 인명록을 생성(v3, 부서명 포함, 올바른 조인 룰(ON) 적용)
보고용으로 좀 더 편하게 보여지도록 고쳐야 한다고 지적받음
SELECT emp.*, dept.id, dept.name AS 부서명
FROM emp
inner join dept
ON emp.deptId = dept.id;
사장님께 드릴 인명록을 생성(v4, 사장님께서 보시기에 편한 칼럼명(AS))
SELECT emp.id AS 사원번호,
emp.name AS 사원명,
DATE(emp.regDate) AS 입사일,
dept.name AS 부서명
FROM emp
INNER JOIN dept
ON emp.deptId = dept.id
order by 부서명, 사원번호;
3개 Join할때는 Join따로 on 따로 맞춰줘야함 (ex) join title body 불가능)
FROM emp AS e; 해서 닉네임을 붙일때 AS는 생략이 가능해서
FROM emp e로 쓸 수 있다
TRUNCATE(AVG(내용), 0) -> 소수점 버리기
HAVING = WHERE -> 하지만 where가 group by 보다 먼저 실행되기 때문에 group by 이후에 where로 조건을 따질 수 없다. 그래서 having을 사용한다.
예를 들어 ~별 ~결과를 봐야한다고 하면 그룹핑해야 한다고 생각하면 된다.
국가별 ~~ 석유 사용 현황 -> 국가로 그룹핑
연령별 ~~ 투표참여율 -> 연령으로 그룹핑
지역별 ~~ 초등학교 개수 -> 지역으로 그룹핑
도시별 ~~ 평균 주택 가격 -> 도시로 그룹핑
Customer 테이블에서 국가별 회원 수 보기
SELECT Country, COUNT(Country)
FROM Customers
GROUP BY Country
SELECT Country, City, COUNT(City)
FROM Customers
GROUP BY Country, City
일반적으로 select문은 from > where > group by > having > select > order by 순으로 실행된다.
where가 group by 보다 먼저 실행되기 때문에 group by 이후에 where로 조건을 따질 수 없다. 그래서 having을 사용한다.
SELECT , country, count() cnt FROM Customers
group by country
having cnt > 5
찾고자하는 문자열을 %기호와 조합해서 사용. 여기서 %는 나머지 문자를 의미
'A%' : A로 시작하는 문자열
'%A' : A로 끝나는 문자열
'%A%' : A를 포함하는 문자열
SELECT FROM Employees
where LastName like 'D%';
Employees 테이블에서 LastName이 D로 시작하지 않는 행만 조회
SELECT FROM Employees
where LastName not like 'D%';
CEIL, ROUND, FLOOR
CEIL() : 올림
ROUND() : 반올림
FLOOR() : 버림
1.2를 반올림
SELECT ROUND(1.2);
Products 테이블의 Price 컬럼값들을 반올림한다.
SELECT ROUND(Price) FROM Products;
AVG, MAX, MIN, SUM, COUNT
AVG(컬럼) : 컬럼의 모든 행의 평균값 구하기
MAX(컬럼) : 컬럼의 모든 행중 최대값 구하기
MIN(컬럼) : 컬럼의 모든 행중 최소값 구하기
SUM(컬럼) : 컬럼의 모든 행의 합 구하기
COUNT(컬럼) : 컬럼의 모든 행의 개수를 구하기 (NULL값은 카운팅에서 제외됨)
SELECT count(CategoryName) FROM Categories;
CONCAT(문자1, 문자2, 문자3 ...)
문자들을 이어 붙여줌.
문자열 'taejin'과 'cha'를 이어 붙이기
select concat('taejin', ' ','cha') as name;
Employees 테이블의 LastName과 FirstName을 이어 붙여 FullName이라는 새로운 컬럼으로 만들기
SELECT EmployeeId, BirthDate, Photo, Notes, concat(LastName, ' ', FirstName) as FullName FROM Employees;
SUBSTR(대상문자, 시작위치, 자르는길이)
문자열을 잘라줌
select substr('taejincha', 1, 6) as fisrtName;
Employees 테이블에서 BirthDate 컬럼의 모든 값을 1번째 문자부터 4개 짜르기(년도만 나오게 하기)
SELECT substr(BirthDate, 1, 4) as year FROM Employees
Customers 테이블의 city 컬럼의 값에서 B문자를 찾아 b로 바꾸기
SELECT replace(city, 'B', 'b') FROM Customers;
CURDATE(), NOW()
오늘날짜 구하기
CURDATE : 연월일
NOW : 연월일 시분초
ADDDATE(기준날짜, interval n day), SUBDATE()
기준날짜로 부터 n만큼의 거리(간격)
DATE_DIFF(날짜1, 날짜2)
날짜1과 날짜2의 차이를 구함
select datediff('2022-03-21', '2021-03-21');
DISTINCT
조회 결과에서 중복되는 행을 제거한다.
Suppliers에서 Country를 중복제거해서 조회하기
SELECT DISTINCT Country
FROM Suppliers
정렬
특정 컬럼을 지정해 그 컬럼의 값으로 행을 정렬.
order by 컬럼 asc/desc
asc : 오름차순
desc : 내림차순
select *
from Products
order by Price ASC, ProductID DESC;
별명
특정 컬럼을 새로운 별명을 붙여 사용. 주로 연산이나 함수를 통해 새로 나온 컬럼에 붙인다.
컬럼 as 별명
SELECT ProductId, SupplierId, CategoryId, ProductId + SupplierId + CategoryId as NewId FROM Products;
+, *, /, -
숫자 + 숫자 == 산술 연산
문자 + 숫자 == 문자는 0 취급
컬럼1 + 컬럼2 == 컬럼의 모든 행이 연산.
SELECT 10 + 20;
SELECT 10 * 20;
SELECT 10 / 20;
SELECT 10 - 20;
비교연산
, <, =, !=
결과는 1(참, TRUE), 0(거짓, FALSE)
비교 연산 예제
SELECT 10 = 20;
SELECT 10 != 20;
SELECT 10 > 20;
SELECT 10 < 20;
SELECT 10 >= 20;
SELECT 10 <= 20;
논리연산
and, or
and : 조건이 여러개 일 때 모두 만족해야 맞다고 보는 연산
or : 조건이 여러개일 때 하나라도 만족하면 맞다고 보는 연산
SELECT *
FROM Customers
where CustomerID >= 10
and CustomerId <= 20;
Customers 테이블에서 CustomerId값이 20 이하인것 + CustomerId값이 80이상인 행을 모두 조회
SELECT *
FROM Customers
where CustomerID <= 20
or CustomerId >= 80;
Customers 테이블에서 CustomerId갑이 20 이하인 것 + CustomerId값이 80이상인 모든 컬럼 중에서 city가 'London'인 행을 조회
SELECT *
FROM Customers
where (CustomerID <= 20
or CustomerId >= 80)
and city = 'London';
컬럼 between A and B
컬럼값이 A와 B 사이인 것만 조회
Customers 테이블에서 CustomerId값이 10과 20 사이인 행을 조회
SELECT *
FROM Customers
where CustomerID BETWEEN 10 AND 20;
포함
컬럼값이 A,B,C 인것을 모두 조회
Customers 테이블에서 city 값에 'London', 'Berlin', 'Madrid' 중 하나라도 포함하는 행을 모두 조회
SELECT *
FROM Customers
WHERE City in ('London', 'Berlin', 'Madrid');
작업 13, 회원가입 기능 추가, 아이디 중복 체크, 비밀번호 체크, 필수 입력 정보
작업 14, Controller 추가 및 기능 이전
작업 15, article write, MVC 구조 추가
작업 16, 나머지 기능들 구조 개선
작업 17, 로그인 기능 구현, 비밀번호 시도 횟수 제한
작업 18, 컨테이너 도입, SQL 에러메세지 console에 보이도록 변경
작업 19, 로그인 정보를 저장, member profile 기능 구현
작업 20, 로그인, 로그아웃 체크
작업 21, 게시물 작성시 로그인 정보 저장, 게시물 리스트에서 작성자의 이름이 나오도록
작업 22, 게시물 수정, 삭제시 권한체크
INSERT INTO member (regDate, loginId, loginPw, name)
SELECT now(), UUID(), 'pw', '아무개'
FROM member;
검색속도 줄이는 법
ALTER TABLE member ADD INDEX(login id);
add index 후
select sql_no cache *
from member
wher loginId = 'user2'
-> 모든 데이터를 index화 시키면 속도는 빠르지만, 그 만큼 용량이 늘어나서 손해다.
그러므로 필요한 데이터만 index화 시키는 것이 중요하다 일반적으로 로그인 아이디를 많이 index화 시킨다.
primary key : 자동 인덱스화, not null, unique를 해준다.
unique index : 중복 값을 허용하지 않는 인덱스
작업 23, 게시물 리스트에 검색, 페이징 기능 추가
완
-> 이 로직을 앞으로도 계속 쓸 것이니 틈틈히 공부. (HashMap, ArrayList)
limit 함수는 범위를 지정할 수 있다.
ex) limit 최소, 최대;
like 문법은 검색 속도 저하를 유발시킨다. -> why? Java의 Contains 처럼 Full Scanning을 한다.
제1 정규화 : 하나의 셀에는 하나의 데이터만 넣자. (한 칸에 데이터 한 개)
MYsql 정규화 검색해서 정리
제2 정규화 : 현재 테이블과 주제가 맞지않는 컬럼은 다른 테이블로 이동
제3 정규화 : 일반 칼럼에만 종속된 다른 칼럼을 다른 테이블로 이동
더블클릭하면 같이 바뀜
<'br'> : 강제 줄바꿈 : ' '은 제외
_blank : 새 탭으로 열기
: 공백
display
block(div,section,nav,article 의 기본값)
너비 최대화
한줄을 무조건 혼자 쓴다
inline-block
너비 최소화
한줄에 최대한 여러개 -> 글자
Ctrl A + Shift Tab = 정렬(완벽하진 않음)
inline CSS : HTML 안에서 Style을 통해 변화를 주는 것
padding : 블록안에 여백생성 ex) padding : 100 50 50 50 하면 시계방향으로 여백 생성
margin : 바깥여백 생성
vertical-align
:nth-child(n) : first, second.... n번째 자식
first-child (첫번째만 됨)
last-child (마지막만 됨)
:nth-child(2n) : 2n번째 자식 -> 2n, 3n처럼 쓸 수 있음 같은 태그의 여러명 고를 때
type:nth-of-type(n) : 타입의 n번째 자식
최상위 태그: html
순서대로 head, body 순으로 함
css에서 부르는법 : .별명
복수의 class(별명을 붙이는법): class = "a b" 이렇게 해야됨 (띄어쓰기 중요)
빠른 단축키 : .a tab하면 생성됨
css 부분에서도 자손을 부를 수도 있기 때문에 띄어쓰기를 신경써야함
id : 별명 비슷한것
부를 때는 #abc 처럼 클래스는 .abc와 다르게 #을 붙여야함
** id는 하나밖에 사용하지 못함
border-radius : block을 원형태로 가꾸는 방법
inherit : 상속 (color, text-align의 디폴트)
hover는 왼쪽으로 갈 수록 더 좋다.
tag h1~h6 : 글자 크기 ( #과 같은 기능)
tag ul > li : 리스트 (- 와 같은 기능)
tage ol > li : 셀 수 있 는 리스트 (1,2~와 같은 기능)
** ul과 ol은 자식으로 li밖에 가지지 못한다.
li : list-style 을 통해 .을 없앨 수 잇음 (약자 lisn + tab)
노말라이징 (대표적이고 기본적인것)
body, ul, li {
margin : 0;
padding : 0;
}
마크업 : HTML 구조쌓기
position :
static(디폴트) - 절때 겹치지 않는 상태 (사람 상태)
absolute : 겹칠 수 있는 상태 (유령 상태) (약어: posab + tab)
-> top,bottom 같은 수치가 적용됨
relative : 제한(가둘 수 있다) - 부모가 이 상태 일 때(유령의 집)
display : none; (안보이게 하는 상태)
transform:scale(n,n) 형태 변환
overflow : hidden;
ctrl + / : 주석처리
/* transform : 변형(주변 엘리먼트에 영향을 주지않는) */
/* translateX(-50%) : 자신의 너비의 반만큼 왼쪽으로 이동 */
/* translateY(-50%) : 자신의 높이의 반만큼 위쪽으로 이동 */
transform: translateX(-50%) translateY(-50%);
시맨트 태그
white-space : nowrap;(약어 whs) - 절대 줄 바꿈 금지
overflow : (넘치는 애들 컨트롤)
scroll : 스크롤 생성 (짧아도 스크롤 생김)
-x : x축에 대한 처리
text - overflow : ellipsis; (뒤에 글이 더 있으면 ...이 생김)
hidden : 숨김
visible : 보여주기
auto : 길면 스크롤생기고 아니면 안생김
position : absolute -> fixed; : (줄 내릴 때 따라올 수있게 할 수 있다.) -> 스크롤을 따라 올 수 있게 만드는 용도
tag:hr : 수평선
transition : background-color 5s;(ex 백그라운드컬러 변하는데 시간 5초) (변화하는 옵션 추가)
복수 개의 transition을 줄때는 따로 만드는게 아니고 ,을 통해 나눠줘서 쓰면된다.
ex)transition : background-color 5s, width 3s;
transition의 width나 height를 잘 적용하려면 시작점이 존재해야한다.
color ; transparent; (투명화)
opacity: 투명도
after: 나중에 추가로 붙이는 것
float 했을 떄,
잘 들어가게 정렬하는법
부모에게
.row::after {
content:"";
clear : both;
display:block;
}
flex container: flex-item을 감싸는 무언가(ex)부모)
폰트 어섬 - icons
flex : 자식까지만 flex item으로 만들어줌(본인은 영향X)
폰트 = 글자처럼취급




console.clear();
function -> 메소드 생성
ex)function.hello(){
alert('안녕');
console.log('안녕');
}
hello();
display:none, visibility:hidden, opacity:0 의 차이점
-box-sizing : border-box
->> 반복 숙달!!!
작업 2, 서블릿 생성
작업 3, 구구단 기초
작업 4, 구구단 기초, 파라미터 사용
작업 5, 파라미터에 색상 추가
request.getParameter(""); -> 주소창에 ?"" 내용 요청
PrintWriter out = response.getWriter();
out.print
작업 6, 서블릿이 JSP 파일에게 요청정보를 넘겨줘서 협업이 가능하도록
작업 7, 서블릿으로부터 넘겨받은 파라미터 데이터를 jsp 안에서 활용
작업 8, DB 연결해서 데이터 가져오기
작업 9, DB.sql 추가
작업 10, 게시물 리스트를 브라우저 에서 노출, 서블릿이 DB에서 가져온 데이터를 jsp에게 넘겨주고 jsp에서 출력
작업 11, 반복문을 활용한 리스트 구현
작업 12, 게시물 상세페이지 구현
작업 13, 리팩토링, 메인페이지 추가
작업 14, SecSql 도입(SQL 인젝션)
작업 15, 게시물 삭제 기능 구현, 리스트를 테이블로 표현






작업 16, 페이지네이션, 페이지 한계 설정 x
작업 17, 게시물 작성 기능 구현
작업 18, POST 방식을 활용한 게시물 작성 기능 구현
작업 19, 게시물 수정 기능 구현
작업 20, detail에 수정, 삭제 추가, 수정 페이지 개선
작업 21, 페이지네이션 하는 중
get 방식
post 방식
input type = hidden 이면 안보임
작업 22, 페이지 노출 갯수 조절
작업 23, 이전 페이지, 다음 페이지 버튼 추가
작업 24, DB 접속 정보 중복 제거
작업 25, 회원가입 기능 구현, return false, JS 함수
작업 26, SQL 에러 메세지 콘솔에도 표시되도록
java jsp에서 ctrl shift c 하면 주석처리

작업 27, 회원가입시 로그인 아이디 중복체크
작업 28, 로그인,로그아웃 기능 구현
작업 29, 게시물 작성시 작성자 정보 저장 및 memberId 추가, 로그인 해야 write 가능 하도록
작업 30, 리스트, 상세보기에 작성자 표시, 게시글 삭제 권한체크
ctrl shift r : 찾기

작업 31, 게시물 수정 권한 체크, 글쓰기 로그인 체크, topBar.jspf
작업 32, 디스패처 서블릿 도입, 프로그램의 입구 감소
작업 33, ArticleService 도입, List에 적용
작업 34, ArticleDao 도입
작업 35, Article Dto 도입
학원홈페이지로 프로젝트 참고
Figma : 포토샵 비슷한 사이트(프론트엔드)
작업 2, 실행 환경 세팅
작업 3, MVC, count 변수의 값 초기화 및 증가
작업 4, count 초기화
작업 5, 컨트롤액션
작업 6, 여러가지 리턴타입 실험
작업 7, ArticleController 추가, 게시글 작성,리스트 구현
작업 8, 게시물 테스트 데이터 생성, 작성 로직 중복 제거
작업 9, 게시물 삭제 기능 구현
작업 10, 게시물 수정 기능 구현, 상세보기 구현
작업 11, ArticleService 도입 및 기능 이전
작업 12, ArticleService에 있는 로직을 ArticleRepository로 이전
작업 13, DB 스키마 추가, mybatis, JDBC 드라이버 추가, yml DB 접속정보 추가, mybatis로 CRUD 구현
작업 14, Insert 리턴타입 수정, last_insert_id
작업 15, SQL 일부를 xml로 이전, 설정 필요
작업 16, articleModify 시 입력된 정보만 수정할 수 있도록
@Component

@Controller

@Service

@Repository

@insert (쿼리처럼 사용 가능)
ex) @select("SELECT * FROM article Where id = #{id}")
=> ? 부분을 #{id} 처리해줘야하지 값을 보내줄 수 있다.
@delete
작업 17, 회원가입 기능 구현, 회원 테이블 추가
작업 18, DB 스키마 업데이트
작업 19, 회원 가입 후 가입한 회원의 정보를 화면에 표시
작업 20, 로그인 아이디 중복체크
작업 21, 회원가입시 입력된 데이터의 null 체크
작업 22, Ut.isNullOrEmpty
작업 23, Ut.isEmpty
작업 24, 회원가입시 이름, 이메일 중복체크
작업 25, Ut.f, 문장 구성을 쉽게 할 수 있도록
작업 26, 보고서 양식 클래스 ResultData 생성, getArticle에 적용
작업 27, getArticles, doWrite에 ResultData 적용


ex(성공or 실패, 메세지, 추가데이터)
작업 28, doJoin에 ResultData 적용
작업 29, ResultData에 제네릭 추가, doModify, doDelete 에 적용
작업 30, 로그인 기능 구현, HttpSession
작업 31, 로그아웃 기능 구현, doWrite 수정, DB 스키마 업데이트
작업 32, doWrite 할 때 작성자의 정보 저장, write,modify,delete 로그인 체크
작업 33, doJoin 로그인체크
작업 34, doModify, doDelete 권한체크
작업 35, article/doModify의 권한체크를 Service에서 대신하도록
작업 36, ResultData에 dataName 추가, SQL 로거 추가
작업 37, JSP 연결
주제고민!