자바 웹을 다루는 기술

[MVC 패턴 정리(AJAX)]xml을 이용한 스프링

피아마수 2023. 8. 29. 17:26

 

controller 호출방법

form을 갖고 호출 --> jsp 로 출력을 해줬다  setAttribute 로 전달한키를 갖고 값을 출력한다.

  1. get

  2. post

json을 갖고 호출 -> 순수 문자열로 출력, 서버에서 전달할 키값으로 js를 통해 값을 출력한다.

 

 

controller 는 model의 수행결과를 view에 전달해주던가 아니면 문자열로 결과를 전달!

 

view는 출력만을 담당한다 , 다음 실행을 위한 링크 출력도 담당한다. 입력값 설정을 잘 해줘야한다.

링크 출력

get/ post -> 페이지를 이동한다

js - > ajax로 불러줄수있다. 동적으로 화면에 반영할 수있다.

 

 

 

면접 질문!!!!!

서버에 전달하고 페이지를 다시 받아오면 데이터의 크기가 크기때문에 오래 걸린다. 이런부부을 없애기 위해 탄생한게 ajax! 1바이트만 바꿀때조차 페이지를 다 받아오면 개손해기 때문에 사용한다.

AJAX

일부분만 바꾸고 나머지의 출력은 그대로 둔다. (((비동기! -> 서버에 있는 함수 호출 (이해를 위함. 다른사람 이해불가))))

 

 lib 추가 필요 없음! 

ajax XHL HTTprequest - > 이거는 서버에서 불러오는 원본이다. 그래서 편리한 사용을 위해 래핑해서 사용한다. 내 함수로 변경해서 쓰면 나중에 그 함 수 부만 바꾸면 되기 때문에 

밑에 ajax모두  XHL HTTprequest를 사용한다. 그래서 뭐가 더 좋다고 할 수없다.

 

ajax fetch -> timeout같은건 내가 코딩해주면 되기때문

 

단점, lib 추가 필요! -> 종속성이 있으면 안될 때는 사용하지 못해

ajax jquery $.ajax() - >이전까지는 이걸 많이 사용햇음

 

ajax axios() - > 이젠 이거 사용하는 추세, 기능이 제일 많고 특정시간후에 응답없을 시 요청을 취소한다.

 

함수 호출은 ()를 갖고 호출함 을 명시한다.

 

비동기를 위해 공간의 제약 없이 호출하는 방법 

fetch, ajax, 링크로도 가져올수있지(href, form태그)

 

스프링 

컨트롤러

함수 호출을 위해서 controller 안 에 함수를만들고 그함수에 어노테이션을 통해 url명을 만든다.

필요한인자들은? 

DTO를 만들어서 전달 DTO안에 필드를만들면 전달 가능한거지

 

fetch (url, 추가옵션)

추가 옵션 (get,post,header)

header (content-type, cookie)

요새는 header에 key값을 넘겨서 사용할 수잇다.

함수호출시 url을 사용한다고 생각하자!

 

fetch 가 왜 비동기인가?

 

동기 : 함수를 호출햇을때 그 함수의 수행시간이 10분이라고 치자 그때 딱 걸려서 10분동안 다음 작업을 수행 할 수 없다

           -> 순차실행

비동기 : 함수를 호출하고 나서 결과 값이 나오지 않아도 다음 것을 실행할수있다 근데 다음작업에서  함수에서 받아와야 하는 값을 받아오지도 않고 사용하는 경우가 생길 수있다.

 

promise

비동기 일 때 미래에 일어날 일에 대한 약속을 갖고 있다.!

10분뒤에 함수의 결과 값을 받겠다

10분뒤에 함수의 결과 값을 받으면 어떻게 쓰겠다를 명시

함수에서 리턴이 된다 - > 하나의 사건! -> 이 이벤트를 처리하는 핸들러를 통해 작업 내용을 받아오면 후처리할 코드를 지정해준다.

비동기 함수 . then -> 리턴이 되면 then을 실행해라

성공 상태코드 200이 왔을때 수행한다.

then(response - > response.json()) -> 응답에서 json을 가져옴

response -> response.json()

response - > responce.text()

respontse - > response.binary() - > 이미지

읽기 json변환

 

서버에서는 text로 보내줌 이걸 내가 읽어서 json으로 변환함 paser를 통해서

위에서 response를 통해서 받아온데이터를 json으로 변환한다.

then(json - > { 코딩}) json 변환이 완료되면 이걸 진행한다.

-->이작 업 모두 promise라는 객체를 가지고 진행한다.

then이 완료 되었을때 동작할 이벤트 핸들러를 갖고 있다.

 

then만으로도 사용할 수 있다.

내부적으로 쓰레드로 진행한다 시간을 나눠서 진행할 수있다.

 

ajax

성공코드 200이 넘어오면 실행

success : r - > {

 

}

실패일 경우에 실행

error : e -> {

 

 

}

function (){

r =await add()

console.log(r);

}

기다려라 끝날때까지console.log(r);의 실행이 진행되지 않는다. 하지만 console.log(r); 내용이 다 진행되지 않아도 바로 리턴한다.

놀랍게도 함수리턴되면 console.log(r);의 실행이 진행된다.

async -> 비동기 함수 앞에 붙는 거

 

비동기 함수는 await 키워드를 써주면 된다.

기억은 then과 await만 기억하면된다!

 

https://velog.io/@khyup0629/javascript-async%EC%99%80-await%EC%9D%98-%EA%B0%9C%EB%85%90%EA%B3%BC-%EC%82%AC%EC%9A%A9%EB%B2%95

 

[javascript] async와 await의 개념과 사용법

자바스크립트는 싱글 스레드 프로그래밍 언어이기 때문에 비동기 처리가 기반입니다. 비동기 처리는 그 결과가 언제 반환될 지 알 수 없기 때문에 동기식으로 처리하는 기법들이 사용되어야 하

velog.io

 

aJax

$.ajax()

$.get() -> get 방식으로

$.post() - > post방식으로 

$.ajaxForm() -> 폼의 데이터 다 보내겠다

 

 

ajax로 json을 통해 하나의 board를 전달하고 싶을 때

public JSONObject getJSONObject() throws Exception {
    JSONObject json = new JSONObject();

    Class cls = this.getClass();
    for (Field field : cls.getDeclaredFields()) {
        json.put(field.getName(), field.get(this));
    }

    return json;
}

public Map<String, Object> getMapObject() throws Exception {
    Map<String, Object> map = new HashMap<>();

    Class cls = this.getClass();
    for (Field field : cls.getDeclaredFields()) {
        map.put(field.getName(), field.get(this));
    }

    return map;
}

JSONObject()안에 넣어서 객체 하나를 json으로 바꿔서 전달하는 방법도 있다.

jsonObject.put("board",new JSONObject(board));

 

스토어드 프로시저 사용이유

 

1. 테이블 구조를 오픈하지 않아도 된다. 테이블 여러개에 나눠서 insert구문을 진행해야하는 경우가 많기 때문에 이런 부분도 한번에 할 수있다.

 

2. 서버에서 DB에 sql을 주면 sql구문이 컴파일 되어 실행된다.

insert구문 10건이 있으면 컴파일 -> 실행을 10 번한다. 서버와의 왕복 10번

프로시저로 되어있으면 실행만 10번한다.  DB에서만! 서버와의 왕복 1번 -> 이게 낫다고 볼순없다

 

현업에가면 프로시저를 잘 볼 수 없기 때문

 


 

첨부파일 추가 하는거 board 테이블에 컬럼으로 하지 말것 검색하기는 쉬움 하지만 여러개를 등록못함

확장성 떨어짐

 

그래서 정규화!

 

파일 형식도 저장해야하네;; 불러오기 위해 

등록날짜도 , 삭제 -> 안함? -> 데이터베이스에 기록이 남아있어야한다. del_yn

첨부파일 저장 contents BLOB binary 데이터저장하는 변수  -> 요새는 안쓴답니다~ 빼주세요 서버에 걍 저장함ㅋㅋ

default의 'N' 작은 따옴표 때문에 오류생길수 있음

 

 

CREATE TABLE UPLOAD_FILE_INFO 
(
  UFI_ID NUMBER NOT NULL 
, BOARDID NUMBER 
, FILE_NAME VARCHAR2(20) 
, FILE_SIZE VARCHAR2(20) 
, CONTENT_TYPE VARCHAR2(20) 
, REG_DATE VARCHAR2(20) 
, DEL_YN CHAR(1) DEFAULT 'N'
, CONSTRAINT UPLOAD_FILE_INFO_PK PRIMARY KEY 
  (
    UFI_ID 
  )
  ENABLE 
);

18장

 

프레임워크

반제품

 

 

면접질문!!

라이브러리 , 프레임워크의 차이

프레임워크는 틀을 개발자가 벗어날수없다 제어 흐름을 바꿀수 없다 -> 대체 불가능

라이브러리는 선택권이 개발자에게 있어서 원하는대로 제어 흐름을 바꿀수있다. ->대체 가능

 

 

리팩토링

함수 안에서의 기능을 몇줄 하는게 좋을까?

줄일수있는대로 줄여야한다. 3줄;;?

함수명을 보고 얘가 무슨일을 하는지 명확히 알수있도록해야한다.

함수명의 길이는? 제약없다!

 

 

 

 

프레임워크

1. EJB 이거 보다 가볍다

2. 제어역행

-> 의존성 역전원칙 -> 느슨한결합

3. 의존성 주입 (DI)

객체를 직접생성하지 않는다 -> 어노테이션을 통해서 주입!

4. 관점지향 

로고 관리?

5. 영속성과 관련된다양한 서비스

6. 수많은 라이브러리, 연동기능

 

스프링만들기

1. lib에 라이브러리를 추가해서 Spring을 진행

2. 라이브러리를 자동 관리해주는 툴을 사용해서 진행

     maven

     gradle

 


19장

 

사용할 클래스, 사용될 클래스

A obj              =    new B();

 

B는 A를 상속받았음 B는 의존성이 있다

new B()해서 외부 주입해서 동작할 수있는게 스프링의 특징

 

 

 

강한결합

객체 new 해서 그 변수에 지정해서 사용하는 것 (변경시 코드를 고쳐야함)

약한결합 

시스템에 의해 상속관계에 있는 변수들끼리 주입되어 사용되는것(변경시 코드를 고치지 않아도 된다. 모듈만 바꿔낌)

 

강결합 코드 -> 약결합코드로 바꿀때는 클래스명을 변경해서 컴파일 오류를 쓰이는걸 다 찾아서 수정한다.

 

 

MVC

책에서는 model, service, controller 를 전부 인터페이스를 만들고 다 상속 받아서 사용하고 있다. 쓸데 없이 interface와 구현체가 많이 생긴다 코드를 추가해야할 것이 많이 생긴다.

 

의존성주입

1. 생성자

final private BoardDAO boardDAO;

-> 실행 도중 변경되지 않게 하려고 

public BoardServiceImpl(BoardDAO boardDAO){

this.boardDAO = boardDAO;

}

final로 설정을 하면 생성자를 통해 초기화를 안해주면 바로 컴파일 에러가 뜨면서 사용할 수없다 기본생성자를 통해서 아무것도 안넣어주면 에러뜸

구문오류로 바꿈

2. setter

설정되지 않아도 코드가 돌아갈수있다.

public void setBoardDAO(BoardDAO boardDAO){

this.boardDAO = boardDAO;

}

실수로 setBoardDAO를 빼먹을 수 있다 그러면 null값뜨면서 논리오류발생

 

논리 오류를 범할 수있다.

3. 어노테이션

 

의존성 주입을 할때 객체를 직접 만드는게 아니라 객체 만드는것에 관한 것을 내가 외부파일에 작성한다. 

 

자바application 스프링 실습

 

 

xml 파일을 만들어준다.

 

스키마! 태그에 구문이 있다

변수(태그들) 선언과 크기정보에대한 내용들로 구성되어있다 마치 테이블 구성처럼

<!DOCTYPE beans PUBLIC "--//SPRING//DTD BEAN//EN"
				"http://www.springframework.org/dtd/spring-beans-2.0.dtd">

 

beans라는 이름으로 사용가능!

 

한줄로도 태그를 작성가능하다!

constructor-arg는 생성자에 매개변수로 들어가는 변수를 초기화해준다.

name 값이 없는대신 타입을 알아서 찾아다가 변경해주므로 값을 대입할 때  예를 들어 int형으로 변경가능한지 확인해봐야한다. 순서대로 대입되게 되는데 해당하는 순번의 타입으로 변경되지 못하면 에러뜬다

property는 클래스 안의 멤버변수를 초기화 해준다

value는 해당하는 변수에 들어가는 값을 의미

bean의 id 속성에는 변수명이 들어가고 class에는 거기에 대입해줄 클래스 의 위치가 들어간다.

 

근데 이때 xml의 위치와 class의 위치가 다른 패키지에 있으므로 xml에서 클래스에 접근가능하도록해주려면 interface와 class를 public으로 전환한다.

<beans>
	<!-- new해서 대입하는걸 여기서 해주는거임 -->
	<!-- id는 변수명 class는 거기에 객체를 생성해서 대입할 클래스명 -->
	<bean id="personService" class="com.spring.ex01.PersonServiceImpl">
	<!-- 클래스안에 멤버변수를 초기화해줌 -->
	<!-- 스프링과 대입해서 사용할 클래스의 패키지가 다르다!! 
		xml에서 접근하도록 하려면 클래스나 인터페이스를 public으로 선언한다.-->
		<property name="name">
			<value>홍길동</value>
		</property>
		<property name="age">
			<value>10</value>
		</property>
		
	</bean>
</beans>

 

 

이를 이용하면 sayHello()에 대한 함수 내용이 변경되어도 호출하는 부분의 코드는 변경되지 않아도 실행이 가능하다 sayHello()함수를 다르게 재정의한 class가 있으면 xml에서 대입할 클래스의 경로명만 바꿔주면 된다.

 

public interface PersonService {
	void sayHello();
}
public class PersonServiceImpl implements PersonService {
	private String name;
	private int age;
	
//	public PersonServiceImpl(String name, int age) {
//		this.name = name;
//		this.age = age;
//	}
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}
	
	public void sayHello() {
		System.out.println("이름 : " + name);
		System.out.println("나이 : " + age);
	}

}

호출부인 main부분을 변경하지 않아도 변경된 내용으로 호출 가능하다.

public class PersonTest {
	
	public static void main(String[] args) {
		/*
		 * PersonServiceImpl personService = new PersonServiceImpl();
		 * personService.setName("홍길동"); personService.setAge(10);
		 * 
		 * personService.sayHello();
		 */
		//이코드를 수정하지 않고도 sayHello()함수를 다른 기능을 하도록 수정할수잇다.
		BeanFactory factory = new XmlBeanFactory(new FileSystemResource("person.xml"));
		PersonService person = (PersonService) factory.getBean("personService");
		//하드코딩으로 글자를 입력하기 때문에 null이 입력될 수있다.
		
		if(person != null) {
			person.sayHello();
		}
	}

}

 

 

member.xml

 

setter로 할때는 property태그에 name을 통해서 값을 셋팅해주면된다. 근데 memberDAO 이거는 클래스 값을 대입해야하므로 bean을 선언하고 참조변수 값으로 ref를 통해서 대입이 가능하다. bean은 memberService는 MemberServiceImpl을 대입해서 controller 느낌인 MemberTest1.java에서 사용할 수있도록해야한다. 이 안에서으 멤버 변수를 초기화 해준다.

 

생성자를 통해서 할때는 constructor-arg태그에 ref 속성을 통해서 클래스를 대입해 줄 수 있다.

<!DOCTYPE beans PUBLIC "--//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">

<beans>

	<bean id="memberService" class="com.spring.ex02.MemberServiceImpl">
		<property name="memberDAO" ref="memberDAO"></property>
		<!-- <constructor-arg ref="memberDAO"></constructor-arg> -->
	</bean>
	<bean id="memberDAO" class="com.spring.ex02.MemberDAOImpl">
	</bean>
</beans>

 

public class MemberServiceImpl implements MemberService{
	 private MemberDAO memberDAO;

//	public MemberServiceImpl(MemberDAO memberDAO) {
//		this.memberDAO = memberDAO;
//	}
	public void setMemberDAO(MemberDAO memberDAO) {
		this.memberDAO = memberDAO;
	}
	
	@Override
	public void listMembers() {
		memberDAO.listMember();
		
	}
}

 

 

public class MemberDAOImpl implements MemberDAO {

	@Override
	public void listMember() {
		System.out.println("listMembers 메서드 호출");
		System.out.println("회원정보를 조회합니다.");
		
	}

}

밑에 있는 메소드를 사용하려면 3가지 jar파일이 있어야함

bean 객체가 저장되어있는 member.xml파일을 읽어온 후 거기서 키로 저장된 memberService의 객체를 가져와서 memberService를 통해 listMembers() 함수를 불러온다.

public class MemberTest1 {
	public static void main(String[] args) {
		BeanFactory factory = new XmlBeanFactory(new FileSystemResource("member.xml"));
		MemberService service = (MemberService) factory.getBean("memberService");
		service.listMembers();
	}
}