[Springboot] Springboot 스터디 7일차
in Study on Springboot
service.read
모델의 역할은 데이터를 담고 있었다. 모델에 담은걸 뷰 페이지에서 쓸 수 있었다. files라는 모델 속성 가져와서
th:each
file이라는 객체 쓸건데 file
fileDownload로 요청을 보낸다
그럼 요청 처리하라 컨트롤러를 만들어줘야한다(요청 받아서 처리할) 그리고 uri매핑을 해줘야한다.
@RequestParam을 Map이라는 컬렉션으로 전달받겠다.
파일 생성, 복사 할 수있는데 그떄 이런 파일같은 경우 우리가 바이트(용량)이 있는데 컴피터는 연산할수 있는 속도가 있어서 한번에 몇기가 몇테라 이걸 입출력으로 전송해줄 수 있는 건 아님.
시스템 안에서 다른 공간에도 메모리가 할당되어있어서 하나의 프로그램 안에서 몇테라씩 용량 주고받긴 힘듬.
파일 가진 용량을 전송하기 위한 작업이 필요.
어느정도의 단위로 해서 버퍼에 실어서 그 버퍼씩 데이터 보내고 전달받아와서 다시 파일로 전달받은 걸 다른 계층으로 보내주는 작업이 필요하다.
이 컴퓨터에 저장되어있는 파일을 외부로 전송
파일 다운로드라는 건 파일에 업로드 되어있는 걸 읽어들여와서 웹페이지로 (웹 어플리케이션)으로 전송해줌으로서 다운로드 시킴.
파일 객체 가져와서 정상적으로 전송하기 위한 작업들이 필요하다.
각각 브라우저마다 갖고있는 인코딩 방식도 있어서 파일 데이터를 넘겨줘야한다. 파일 이름도 마찬가지.
그런거에 대한 부분을 다 파악하기 쉽지 않음.
파일을 read.html에서 파일경로로 fullname과 filename을 요청보내면 filedownlaod로 매핑받은 곳으로 전달받고 전체경로와 파일명을 이용해 inputstream, outputstream이 가능하다. 이 객체들로 서버로 전송해주는 작업을 한다.
import 했고
파일을 pc에서 가져온거 file inputStream이라는 객체가 필요하다.
반대로 파일 전송하는 쪽은 웹페이지. 여기서 servletinputStream, servletOutputStream이 있는데
출력을 웹페이지로 해줌.
가장 처음 해줘야 하는 작업은 브라우저마다 맞는 인코딩 방식 적용해줘야한다.
인코딩 방식 적용하는 것도 파일 데이터 자체는 원본 자체 가져오는데 파일명은 예를들어 엣지 브라우저나 ms explorer, chrome등 각 적용되는 방식이 있다.
브라우저에 정상적으로 인코딩 하려면 파일 인코딩에 적힌것 처럼 인코딩 해줘야한다.
그 다음에 붙는 건 response객체에 붙는건 웹 페이지에 응답해줄때 여러가지 헤더객체에 여러가지 붙는다.
웹 페이지로 응답하기 위한 규칙을 만들어줌.(사실 이거는 다 알려면 공부해야할게 되게 만ㄶ다.)
전체경로 가지고 가져온 파일객체로 객체 생성해주고 servletoutputstream 은 응답 객체
응답할 객체에 대해 헤더 정보.
sevletoutput은 직접생성이 아니라 응답객체에서 가져옴 리스폰스에서 있는 헤더정보나 컨텐츠 타입을 바탕으로 getoutputstream을 호출하면 servlet에 어떠한 형태로 출력스트림을 만들어 줄지 그 인스턴스를 메서드를 통해 가져올 수 있다.
우리 집까지 수도 나오려면 여러 수도가 연결되어 있어서 그거 타고 나온다.
강에 있는 걸 타고 나오게 되는데 강과 아파트 까지 연결된 관이 필요하다. 그리고 아파트에서 우리집까지 오는 관도 필요하다.
강부터 아파트까지 연결되어있는 관을 fileInputStream이라 보면 되고 그 물을 끌어와서 Stream에 연결된 걸(입력 연결객체) 우리 아파트까지 전송할 수 있도록 연결해주고 그 연결 통로 안에는 물을 쓸떄는 당연히 물이 실리고 지금은 파일을 싣는다.(다른 서버에 있거나 다른 곳에 있는 걸 다운) 우리는 파일을 연결통로를 통해서 다운 받고 최종적으로 내 pc모니터, 수도꼭지에서 물이 나오게 하려면 우리 집에서 수도꼭지에 쓰는 통로관이랑 강에서 아파트까지 끌어오는 관은 당연히 다르게 생김.
강에서 끌어오는건 훨씬 굵고 튼튼해야(물 많이 가져오려고) 아파트까지 오는 관은 손씻기에 적합한 관으로 되어 있을 건.
이 서버 컴퓨터에 있는 파일을 가져오는 연결통로는 fileInputStream이고 웹페이지에 보여주는 건 servletOutputStream이다.
그거에 대한 객체가(인스턴스 갖고 있는거) response가 getOutputStream을 호출해서 가져올수 있게 됨.
그럼 fileInputStream은 new InputStream 했는데 OutputStream은 왜 new OutputStream이 아닌 response.getOutputStream이 아닌가?
이건 response객체가 outputsteram에 대한 인스턴스를 가져오는 것.
파일을 연결할 수 있는 통로는 그때그떄 여러개를 만들 수 있다.
우리집으로 들어오는 선이나 관 이런게 수도관도 있겠지만 인터넷 연결하기 위한 랜선도 있을거고 그거 외에 가스관도 있고 여러개의 연결통로가 있을 수 있다.
그런 여러가지 물이든 인터넷 연결 선이든 가스 관이든 우리지베서 사용할 떄 쓸 수 있는 건 우리집으로 수도관이 여러개 있으면 가능할 수 있겠지만. 우리집으로 들어오는 관은 하나로 만들고 화장실1, 화장실2, 싱크대 등 나눠서 쓸 수 있다.(수도관이 그렇게 많이 필요하지 않음)
마찬가지로 outputSTream도 new로 객체 여러개 만드는 거보다 하나로 만드는게 낫다 new는 객체 생성하면 서버에서 킬떄마다 객체생성ㅎ아니까 성능 저하가 됨.
입력해서 가져온 파일을 조금씩 출력해줄 것.
바이트 배열 만들어서 1024바이트를 담게 만들고 1024바이트는 1kb가 되고 fileInputStream에 read가 되어있는데 file이 1mb면 1kb 의 1024개씩 가져오면 1메가가 되는데 이걸 한번에 가져오는게 아니라 조금씩 읽어옴(1kb)씩
fileInputStream의 read를 쪼금씩 받아옴.
더 이상 가져올 데이터가 없으면 -1을 반환
마지막 1024 다음 가져올 거 없을 때 -1 만나면 반복 안하고 끝냄.
그 데이터를 가져온 걸 servletOutputStream으로 출력 1kb바이트씩 출력 해줌.
1kb씩 버퍼에 담아서 웹 페이지에 담아서 조금씩 보내주는 것. 그게 다운로드 받을 떄 조금 씩 쌓여서 한 파일이 됨.
한글명으로 된 강아지를 어떻게 인코딩을 해야 특정 브라우저에서 될지 인코딩하고
그 밑은 헤더에 적용된 설정
그리고 input, output스트림으로 조금씩 내려받을수 있도록 outputStream으로 출력.
조금씩 가져오는 이유? 서버는 한번에 전송해줄 수 있겠지만(가능은 함) 인터넷으로 쇼핑하면 하루 내지 이틀이면 배송이 오는데 그 박스가 안 훼손되서 오긴 힘듬(택배사를 거쳐 기사님을 거쳐서 우리집에 오는데 먼지가 조금이라도 안 묻을 수 없다) 그런 경우도 있고 그런 물건들이 청바지 하나를 샀다 하나는 문제가 안되는데 청바지를 한번에 우리집에 2천장을 배송해라 하면 적어도 큰 트럭이 필요한데 우리집에 트럭을 주차할 방법이 없음.
마찬가지로 만약 4기가 영화 받으려는데 당장 영화파일 받으려는데 내 컴퓨터에선 4기가를 한번에 처리할 만큼 메모리 공간이 확보 안되어 있으면 (용량 말고 램 말하는 거) 만약 8기가인데 6기가를 쓰고있으면 4기가영화를 한번에 다운 받기는 힘드니까 10메가씩 받으면 메모리 할당량도 적고 데이터 유실된 가능성도 적어짐.
돈의 문제도 있겠지만 물건 사는데도 금을 몇만 톤을 산다 치면 그걸 저장할 창고는 있어야한다. 아님 그걸 트럭으로 가져오면 집 안에서도 창고에 넣어줄 사람이 필요한데 작업할 사람이 한사람 밖에 안되면 엄청 느릴 것.
많은 물건 요청해도 내가 받아들일 수 있는게 안된다.
받아들일수 있는 메모리 용량의 한계 , 메모리 유실 가능성
데이터 요청 했는데 문제있으면 다시 전달해서 받게하는 프로토콜 방법이 있는 데 그런 여러가지 이유때문에 조금씩 가져옴. 게임이나 영화 받으면 100기가 게임을 한번에 못받는거라고 생각하자 그리고 컴퓨터의 성능도 있지만 인터넷의 성능도 있음. 10기가 이상을 못보내는 회선인데 100기가를 한번에 못 받는 것과 동일하다.
그래서 통신, 네트워크 이런거도 필요하다. 자바
ctrl+h 하면 파일 검색해서 찾기 가능
전체 다운로드는 파일 가지고 있는거 여러개인데 2개가 있으면 이름 하든지 해야하지만 게시글 이름으로 압축파일 이름 지어주도록 할것.
게시글 이름 넘겨주고 번호 넘겨줘서
게시글 번호 알면 그 게시글에 딸려있는 파일들을 조회해서 그 파일에 전체경로를 찾아올 수 있음.
글번호와 제목 넘겨줄 것.
예외 발생할 수 있어서 exception 추가.
한번에 임포트 하려면 ctrl + shift +o 하면 된다. 아래 작업도 다운로드 하기 위해서 저 정보(파일 리스트에 들어있는 파일들을 하나씩 꺼내옴.)
fullname을 전체 경로로 해서 그 파일을 가져온 걸 파일 인풋스트림으로 꺼내오고 조금씩 읽어서 zip파일에 출력하고 최종적으로 응답을 해주게 되는 작업.
아까는 서블릿이였는데 지금은 zip파일(zipEntrty)
일단은 파일 하나씩을 inputStream으로 읽어와서 출력함.
출력하는건 zipoutputstream으로 되는 것 압축파일로 만들고 그 압출파일로 만든건 inputstream으로 만든걸 웹 페이지에 출력해줌.
앞에선 단일 파일이였는데(파일명, 응답객체ㅔ, 파일 하나씩 읽어서 웹페이지에 바로 씀) 근데 여기서 먼저 해야할 작업은 반복을 통해서 한 파일씩 꺼내서 그 파일들을 하나 꺼내와서 계속 출력을 해주는데 그건 압축파일에 출력해서 완성하는 작업을 끝내고 그 압축파일로 된걸 압축파일에 담아서 서블릿 아웃풋 스트림에 쓰기를 해줌.
ZipEntry는 압축하면 여러파일이 폴더 들어가는거 처럼들어가는 항목항목들을 말함. 하나의 파일 이름 꺼내오고 그거 해서 파일 객체 만듬.
그 파일 이름을 기준으로 하나의 파일 항목 만듬. 압축 파일에 들어갈 파일 항목을 만들어서 다음 엔트리에다가 넣어줌.
실제 데이터는 zout.write(buffer,0,length)에서 넣어주게된다.
파라미터 넘길 떄 &로 연결해야 하고 그 연결 되는 바로 뒤의 객체에는 $가 없어도 된다.
파일명 뒤에 x번호 누르면 파일 삭제되게 해줄것. 그러려면 x아이코닝 필요할 것.
ajax는 어떤경로와 어떤방식으로 요청 보낼 건지.
메서드 방식으로 보낸다(get인지 post인지 지정해주고 어떤 파라미터 넘길 건지.)
우리는 파일 넘버하고
fileNo과 filePath를 가져온다.
이 span태그의 부모요소 얘를 딜리트 해서 없애준다.
비동기 통신
Ajax 는 비동기로 통신.
글 쓰기 할 때도 글 쓰기 전에 두개를 동시에 쓸 수 있나? 제목 쓰고 내용 하고 글 쓰기 완료 하고 다시 글쓰기 화면 요청하고 글 쓰고 눌러야 두번쨰 글이 작성가능.
근데 지금과 같은 화면엔 이 화면 안에서 얘 삭제 하고 처리 끝나면 화면 유지가 되어야 한다.
동기식 방식은 form태그로 됨
얘도 form방식으로 하면 새로고침 하면 다시 재응답해서 할 수 있다. 얘도 비동기식으로
동기식은 화면 재응답(한번 새로고침 된다) 비동기식은 화면이 그대로 유지가 됨.
비동기식으로 해야되는게 파일삭제라던가 댓글이라던가. 만약 댓글쓰기 화면이 따로 열리고 다시 그 게시글로 이동하면 엄청 불편할 것.
댓글 같은 것도 그 게시글 상태에서 그 댓글 쓰면 비동기로 쓰고 그 댓글 ㅜ분만 새로 응답.
내가 쓴 댓글에서 그 댓글이 있는 목록만 다시 뿌려주면 된다.
그럼 페이지 전체가 다시 뜨는게 아니다.
그럼 페이지 전체가 다시 불러와 질 필요가 없다.
파일만 삭제되고 전체는
RESTful API는 조회 수정 삭제 이런걸 정확히 지키면서 작성.
풀스택이라 get,post만 써도 되지만 프론트, 백 나누면 restful로 해야된다.
그거에 맞게 타입을 지정해서 짜주면 된다. 나는 컨트롤러에서 그 규칙에 맞게끔만 짜주면 된다. 조회요청이면 어디로 가게하고 삭제요청이면 어디로 가게하고
프론트 백 나누면 get post만 써도 되기는 하는데 restful
자원을 요청 (표현하기 위해서) 기본적으로는 데이터 삽입하고 수정하고 하는건데 이 4가지에 대한 규칙을 잡아둠. post,get, put ,delete 잡고 그거에 맞게 매핑을 하는 식으로 하는게 restful 그래서 http url을 통해서 자원 명시하고 http 메서드 (get,post,put, delete) 해당 crud 적용해서 사용한다.
이런게 필요해지는게 바로 클라이언트가 다양화 되었기 떄문 서버는 저 규칙대로 만들면 되고 클라이언트는 저 규칙대로 작업 된다.
이게 rest의 기본 틀.
이거에 맞게끔 우리가 requestMapping이나 이런걸 해주게 됨 (설계의 규칙을 알고 있어야 됨) 꼭 이래야되는건 아니지만 서로간의 약속이 맞아진다. 왜냐면 클라이언트에서 요청하는게 서버에서 통용되는 방식으로 적용되야 내가 수정요청했는 데 그게 수정의 방식으로 사용이 가능하다.
파일확장자는 mapping으로 안쓰거나 언더바 안쓰거나 이런 규칙들이 있다.
그걸 따라서 하는게 restful 하게 개발하는 것.
작성된 파일 목록 비우고 남아있는 파일 목록 갱신하는 방법으로 사용할수 도 있다.
board 패키지 밑에 success파일이 있는데 그 페이지를 이 매개변수로 응답시킴. 이 데이터를 가져와서 board/success로 보낸다.
개발자로 취업해도 공부 계속해야한다.
무엇이든 물어보살 => 커플 여행 가서도 개발공부한다.(노트북 들고 1~2시간 공부한다.)
나중에 자기가 공부한거로 회사 나와서 창업하겠다는 목표가 있었는데 결국은 매일 공부해야하고 매일 공부 한다.
우리는 계속 공부해야 되서
학습하는게 있고 복습하는게 있는데 우리는 어떤 기술에 대해 한번 딱 하고 이해하고 하면 좋겠지만 그렇게는 안된다.
우리는 한번 학습하고 복습하고 복습 *100을 해야한다. 그럼 과정이
학습 검색 복습 응용
검색도 사실 시간이 든다(책이든 구글링이든 이전 코드나 누구에게 질문하든)
한번 학습하고 나서 복습할 때 책에도 안적혀 있고 그때 한거 같은데 이러면 걔를 정확하게 이해하려면 찾아봐야한다. 그리고 이렇게 한번 학습 이뤄지면
어디서 프로젝트에 적용하려면 그때 공부했던거 같은데 그걸 어떻게 해야되는지 기억이 안나면 또 검색하고 다시 복습하고 응용하는 거.
그때 포트폴리오 만드려고 플젝때 한거였는데 그떄 했던거 써야될 거 같아. 근데 뭐라고 쳐야할지 모르겠어 . 그럼 또 검색해야됨. (복습정도까진 아니어도 싹 보고 응용이 된다)
그리고 회사에서 한번하고 끝나는게 아니라 또 찾아보고 또 응용하고 이런식이 된다.
복습도 매번 하게 되지만 결국 검색이 가장 많이 하게 된다.
공부할수 있는 시간이 300시간이면 검색하는 시간이 길어질수록 시간이 뻇긴다. 그래서 검색하는 시간을 줄여야 한다. 가장 좋은건 검색하는걸 나만의 책을 만드는 게 낫다.
블로그에 배웠던 걸 카테고리나 주제로 작성해주면 이제 이 작업이 필요가 없어진다.( 검색이 필요가 없어진다.)
BLOG에 가서 그 기능 찾으면 검색과정이 단순화 된다(시간절약이 아주 좋다)
이 과정이 줄어들고 블로그에 쌓이면 컨텐츠에 쌓이면 어마어마해진다.
이제 블로그 + 깃허브가 도움이 된다.
이걸 많이 쌓은거로 본질적으로 프로젝트 히스토리를 만든다.
검색의 시간을 줄일 필요성이 있다.
했었더거를 응용하고 해애되는게 검색 복습 응용이 들어간다.
xml은 서버 켯 전체 다운로드도 없어져야 되고
글 삭제 하면 파일 남아있으면 안된다.( )
외래키에 undelete
board, board_attach가
boardNo이 연관관계 board_attach 를 이걸 외래키로 지정해서 board테이블의 기본키인 보드 넘버를 참조하게 만듬 보드 테이블의 게시글 하나가 사라지면 외래키로 저장해 둔 attach의 넘버가 사라져야 한다.
board 테이블의 board_no를 지우면 board_attach가 지워지게 해야한다.
board테이블이 데이터 삭제됐을때 보드 어테치 테이블의 넘버가 같은 모든 데이터를 삭제하는게 undelete cascade 방식
외래키는 디비에 대한 작업 보드컨트롤러에서 실제 파일도 삭제해 줘야한다.ㅏ
파일리스트 조회해오고 읽어온 걸 삭제.
리스트를 받아서 그 리스트를 반복하면서 삭제하는 파일.