var formData = $("form[name=Form]").serialize();

$.ajax({
	url: url,
	type: 'POST',
	data: formData,
	processData: false,
	contentType: false,
	success:function(data){
        	 $("#fileJson").val(data);
        	 fncInsert(arg);
	},
	error:function(e){
	alert("업로드중 에러 발생.");
	}
});

 

MultipartHttpServletRequest 오류 발생한 상황에서 확인한 것들

 

1. bean 확인

2. pom 확인

3. ajax에 processData, contentType -> false로 선언

4. jsp-form에 enctype="multipart/form-data" 설정

5. 컨트롤러 확인

 

전부 다 설정되어있는 상태에서 계속해서 오류가 발생함.

 

Multipart 데이터이기 때문에 form.serialize()를 사용하면 안됨

 

1) multipart는 boundary로 구분되어야 하는데 form.serialize()를 사용할경우 json데이터로 전송이 되어 파싱이 안되는 문제 발생.

2) 파일데이터는 file.js를 통해서 new FormData() 개체를 만들어 append하고 있었고, 구분값이 있는 jsp-form 데이터는 ajax 상단에 다시 formData를 선언해서 보내려고함. 두 유형의 데이터를 하나의 변수값에 담으려는 행동을 한 것이 문제.

3) jsp-form 데이터를 보내는 것을 url을 이용해서 파라미터 붙여서 이동하게 해줌.

'JAVA' 카테고리의 다른 글

[JSP] 자바빈 관련 액션태그  (0) 2021.07.18
Spring 핵심 01 : 객체 지향 설계와 스프링  (0) 2021.05.18
Spring 05 : AOP  (0) 2021.05.18
Spring 04 : 스프링 DB 접근  (0) 2021.05.18
Spring 03 : 스프링 빈과 의존관계  (0) 2021.05.18

스프링

  1. 스프링 생태계
  • 필수 : 스프링 프레임워크 / 스프링부트
  • 선택
    • 스프링 데이터 : 디비사용편하게
    • 스프링 세션 / 스프링 시큐리티 / 스프링 배치
    • 스프링 rest docs : api문서를 편하게

 

  1. 스프링 부트
  • 스프링을 편리하게 사용할 수 있도록 지원
  • 톰캣같은 웹 서버를 내장하여 별도의 웹 서버 설치않아도 됨
  • 단독으로 실행할 수 있는 스프링 애플리케이션 쉽게 생성
  • 손쉬운 빌드 구성을 위한 starter 종속성 제공 : 라이브러리에서 하나만 가져오는 것이 아닌 그 하위의 것들도 함께 가져옴
  • 스프링 프레임워크 버전에 맞는 외부 라이브러리를 가져옴
  • 메트릭, 상태확인, 외부 구성 같은 프로덕션 준비 기능 제공
  • 관례에 의한 간결한 설정

 

  1. 스프링의 핵심
  • 자바언어 기반의 프레임워크
  • 자바언어의 가장 큰 특징 : 객체지향언어
  • 스프링은 객체지향언어가 가진 강력한 특징을 살려내는 프레임워크
  • 스프링은 좋은 객체 지향 애플리케이션을 개발할 수 있게 도와주는 프레임워크

 

  1. SOLID : 클린코드로 유명한 로버트 마틴이 좋은 객체지향설계의 5가지 원칙을 정리
  • SRP : 단일책임원칙
    • 한 클래스는 하나의 책임만 가져야한다.
    • 중요한 기준은 변경. 변경이 있을 때 파급효과가 적으면 단일책임원칙을 잘 따른 것.
  • OCP : 개방-폐쇄원칙
    • 소프트웨어 요소는 확장에는 열려있으나 변경에는 닫혀있어야한다.
    • 다형성활용하면 가능
    • EX) 인터페이스를 구현한 새로운 클래스를 하나 만들어서 새로운 기능을 구현
  • 인터페이스 = new 구현객체*
  • LSP : 리스코프 치환원칙
    • 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야한다.
    • 다형성에서 하위클래스는 인터페이스 규약을 다 지켜야 한다는 것.
  • ISP : 인터페이스 분리 원칙
    • 특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.
  • DIP : 의존관계 역전 원칙
    • "추상화에 의존해야지, 구체화에 의존하면 안된다." : 구현클래스에 의존하지 말고, 인터페이스에 의존하라

'JAVA' 카테고리의 다른 글

[Spring] MultipartHttpServletRequest 오류  (0) 2022.05.12
[JSP] 자바빈 관련 액션태그  (0) 2021.07.18
Spring 05 : AOP  (0) 2021.05.18
Spring 04 : 스프링 DB 접근  (0) 2021.05.18
Spring 03 : 스프링 빈과 의존관계  (0) 2021.05.18

AOP

  • 관점 지향 프로그래밍
  • 어떤 로직을 기준으로 핵심적인 관점, 부가적인 관점으로 나누어서 보고 그 관점을 기준으로 각각 모듈화하겠다는 것
    • 모든 메소드의 호출 시간을 측정하려고 할 때
    • 공통 관심 사항(cross-cutting concern) vs 핵심 관심 사항(core concern)
  • AOP가 필요한 상황
long start = System.currentTimeMillis(); 
try{
	validateDuplicateMember(member); 
    memberRepository.save(member); 
    return member.getId(); 
}finally {
    	long finish = System.currentTimeMillis(); 
        long timeMs=finish-start; 
        System.out.println("join = " + timeMs + "ms"); 
}

AOP를 사용하지 않는다면 메소드 호출시간을 측정해주는 것을 포함시켜야한다.

 

시간측정 AOP 등록

@Aspect //이걸 적어야 aop사용가능 
@Component public class TimeTraceAop {

	@Around("execution(* hello.hellospring..*(..))") 
    public Object execute(ProceedingJoinPoint joinPoint) throws Throwable{
    	long start = System.currentTimeMillis(); 
        System.out.println("START: "+joinPoint.toString()); 
        try{ 
        	return joinPoint.proceed(); 
        }finally {
        	long finish = System.currentTimeMillis(); 
            long timeMs = finish-start; 
            System.out.println("END: "+joinPoint.toString()+" "+timeMs+"ms"); 
        } 
    } 
}

서비스 하위로 메소드 호출시간을 보고 싶을 때 : `@Around("execution( hello.hellospring.service.(..))")`

  • 회원가입, 회원 조회등 핵심 관심사항과 시간을 측정하는 공통 관심 사항을 분리.
  • 시간을 측정하는 로직을 별도의 공통 로직으로 생성.
  • 핵심 관심 사항 깔끔하게 유지가능.
  • 변경이 필요하면 이 로직만 변경하면 된다.
  • 원하는 적용 대상을 선택가능.

@Component가 아닌 직접 @Bean으로 참조 했을 때

@Configuration 
public class SpringConfig {
	@Bean 
    public TimeTraceAop timeTraceAop() {
    	return new TimeTraceAop(); 
    } 
}
  • 이 상태에서 @Around("execution(* hello.hellospring..*(..))")라고 한다면 자기 자신인 TimeTraceAop를 생성하는 코드인 SpringConfig의 timeTraceAop() 메서드도 AOP로 처리하게 된다. 따라서 순환참조 문제가 발생하게 된다.
  • 다음과 같이 AOP 대상에서 SpringConfig를 빼주면 된다.
  • @Around("execution(* hello.hellospring..*(..)) && !target(hello.hellospring.SpringConfig)")

 

Ctrl+Alt+L : 코드정렬

인프런 '스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술' 통해 학습 중.

스프링 데이터 엑세스

 

1. 순수 JDBC
2. 스프링 JdbcTemplate
3. JPA

 

H2 데이터베이스 설치 방법

 

1) ./h2.bat (mac에서는 ./h2.sh)
2) jdbc:h2:~/test로 DB 생성
3) ~/test.mv.db 파일 생성 확인
4) 이후부터 jdbc:h2:tcp://localhost/~/test로 접속

The Web Console server could not be started. Possible cause: another server is already running at XXX:8082

8082 포트가 겹쳐서 발생한 오류. 포트 죽여줘야함.

 

순수 JDBC

  • build.gradle 파일에 jdbc, h2 데이터베이스 관련 라이브러리 추가
implementation 'org.springframework.boot:spring-boot-starter-jdbc'
runtimeOnly 'com.h2database:h2'
  • 스프링 부트 데이터베이스 연결 설정 추가 (resources/application.properties )
spring.datasource.url=jdbc:h2:tcp://localhost/~/test
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
  • pstmt = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS); : sequence라고 생각하자
  • spring config 변경
@Bean public MemberRepository memberRepository() {
	// return new MemoryMemberRepository(); 
	return new JdbcMemberRepository(dataSource);
}

 

스프링 통합 테스트

  • @SpringBootTest : 스프링 컨테이너와 테스트 함께 실행.
  • @Transactional : 테스트 케이스에 이 애노테이션이 있으면, 테스트 시작 전에 트랜잭션을 시작, 테스트 완료 후에 항상 롤백. 다음 테스트에 영향 주지않기 위해 사용. (DB에 데이터가 남지 않음)

 

스프링 JdbcTemplate

  • 스프링 JdbcTemplate과 MyBatis 같은 라이브러리는 JDBC API에서 본 반복 코드를 제거해준다. 하지만 SQL은 직접 작성.
  • 순수 JDBC와 환경설정은 같다.
  • spring config 변경
@Bean
public MemberRepository memberRepository() {
	// return new MemoryMemberRepository(); 
    // return new JdbcMemberRepository(dataSource); 
    return new JdbcTemplateMemberRepository(dataSource); 
}

 

JPA

  • 기존의 반복 코드는 물론이고, 기본적인 SQL도 JPA가 직접 만들어서 실행.
  • SQL과 데이터 중심의 설계에서 객체 중심의 설계로 패러다임을 전환 가능하게 해준다.
  • build.gradle 파일에 JPA, h2 데이터베이스 관련 라이브러리 추가
dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' 
    implementation 'org.springframework.boot:spring-boot-starter-web' 
    //implementation 'org.springframework.boot:spring-boot-starter-jdbc' 
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa' 
    runtimeOnly 'com.h2database:h2' 
    testImplementation('org.springframework.boot:spring-boot-starter-test') { 
    	exclude group: 'org.junit.vintage', module: 'junit-vintage-engine' 
    } 
}

spring-boot-starter-data-jpa 는 내부에 jdbc 관련 라이브러리를 포함

 

  • 스프링 부트에 JPA 설정 추가(resources/application.properties)
spring.jpa.show-sql=true //JPA가 생성하는 SQL을 출력 
spring.jpa.hibernate.ddl-auto=none //자동으로 테이블 생성하는 것 해제
  • member 클래스 엔티티매핑
@Entity 
public class Member {
	@Id @GeneratedValue(strategy = GenerationType.IDENTITY) //DB가 알아서 생성되게 한 것을 identity전략이라고 함.
    private Long id; 
    private String name;
  • JpaMemberRepository 생성 (JPQL 사용)
  • 서비스 계층에 트랜잭션 추가
  • spring config 변경
@Configuration 
public class SpringConfig { 
	private final DataSource dataSource; 
    private final EntityManager em; 
    public SpringConfig(DataSource dataSource, EntityManager em) {
    	this.dataSource = dataSource; this.em = em; 
    } 

	@Bean 
	public MemberService memberService() {
		return new MemberService(memberRepository());
	} 

	@Bean 
	public MemberRepository memberRepository() {
		// return new MemoryMemberRepository(); 
    	// return new JdbcMemberRepository(dataSource); 
   	 	// return new JdbcTemplateMemberRepository(dataSource); 
   		return new JpaMemberRepository(em); 
 	}
}

 

스프링 데이터 JPA

  • 리포지토리에 구현 클래스 없이 인터페이스 만으로 개발을 완료할 수 있다.
  • 기본 CRUD 기능도 스프링 데이터 JPA가 모두 제공
  • 앞의 JPA 설정을 그대로 사용
  • 스프링 데이터 JPA 회원 리포지토리(인터페이스) 생성
  • spring config 변경
@Configuration
public class SpringConfig {
	private final MemberRepository memberRepository;
    
    @Autowired
    public SpringConfig(MemberRepository memberRepository) {
    	this.memberRepository = memberRepository;
    } 
    
    @Bean 
    public MemberService memberService(){
    	return new MemberService(memberRepository);
    } 
}
  • 스프링 데이터 JPA가 SpringDatJpaMemberRepository 를 스프링 빈으로 자동 등록

인프런 '스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술' 통해 학습 중.

'JAVA' 카테고리의 다른 글

Spring 핵심 01 : 객체 지향 설계와 스프링  (0) 2021.05.18
Spring 05 : AOP  (0) 2021.05.18
Spring 03 : 스프링 빈과 의존관계  (0) 2021.05.18
Spring02 : 예제(회원관리)  (0) 2021.05.18
Spring 01 : 프로젝트 환경설정  (0) 2021.05.18

스프링 빈 등록방법

  1. 컴포넌트 스캔과 자동 의존관계 설정
  2. 자바 코드로 직접 스프링 빈 등록하기

컴포넌트 스캔과 자동 의존관계 설정

  • 회원 컨트롤러가 회원서비스와 회원 리포지토리를 사용할 수 있게 의존관계 준비
@Controller
public class MemberController {
    private final MemberService memberService;    

    @Autowired
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
}
  • 생성자 주입을 쓰는 것이 제일 좋다.
  • @Autowired : 스프링이 연관된 객체를 스프링 컨테이너에서 찾아서 넣어준다.
  • @Component : 이 애노테이션이 있으면 스프링 빈으로 자동 등록된다.
  • @Component / @Controller, @Service, @Repository
@Autowired
private MemberService memberService;
  • 필드주입 : 스프링이 뜰 때만 넣어주고 바꿀 수 있는 방법이 없다. 잘 안쓴다.

 

자바 코드로 직접 스프링 빈 등록

  • @Service, @Repository, @Autowired 애노테이션 제거 후 진행

SpringConfig.java 파일 생성

@Configuration
public class SpringConfig {

    @Bean
    public MemberService memberService(){
        return new MemberService(memberRepository());
    }
    @Bean
    public MemberRepository memberRepository(){
        return new MemoryMemberRepository();
    }
  }
  • 장점 : 정형화 되지 않거나, 상황에 따라 구현 클래스를 변경해야 할 경우 직접 스프링 빈을 등록하는 것이 더 편하다.
  • 아직 데이터 저장소가 정해지지 않았다는 가상의 시나리오를 정했기 때문에 직접 스프링 빈을 등록하는 것으로 한다.

보충

  • thymeleaf : JSP와 달리 Servlet으로 변환X, 비즈니스 로직과 분리되어 View에 집중.
  • 스프링부트에서는 JSP 자동 설정 지원X. JSP는 jar패키징 불가하여 war패키징해야한다.
  • get : 주로 조회할 때 / post : 폼에 등록할 때

jar

  • 자바 프로젝트를 압축한 파일

war

  • 웹 관련 자원만 포함, 웹 어플리케이션 압축 파일 포맷
  • JAR 포맷과 달리 WEB-INF 및 META-INF 디렉토리로 사전 정의 된 구조를 사용
  • WAR파일을 실행하려면 Tomcat, Weblogic, Websphere 등의 웹 서버 (WEB)또는 웹 컨테이너(WAS)가 필요

인프런 '스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술' 통해 학습 중.

'JAVA' 카테고리의 다른 글

Spring 핵심 01 : 객체 지향 설계와 스프링  (0) 2021.05.18
Spring 05 : AOP  (0) 2021.05.18
Spring 04 : 스프링 DB 접근  (0) 2021.05.18
Spring02 : 예제(회원관리)  (0) 2021.05.18
Spring 01 : 프로젝트 환경설정  (0) 2021.05.18

API

@GetMapping("hello-string") 
	@ResponseBody 
	public String helloString(@RequestParam("name") String name){
		return "hello " + name; 
	}
  • ResponseBody : http의 body부분에 데이터를 직접 넣어주겠다. view사용X
  • RequestParam : HttpServletRequest 객체와 같은 역할.

 

비즈니스 요구사항

  • 컨트롤러 : 웹 MVC의 컨트롤러 역할
  • 서비스 : 핵심 비즈니스 로직 구현 (비즈니스적인 용어 사용_join)
  • 리포지토리 : 데이터베이스에 접근, 도메인 객체를 DB에 저장하고 관리 (개발적인 용어 사용_save)
  • 도메인 : 비즈니스 도메인 객체
  • 아직 데이터 저장소가 선정X. 인터페이스로 구현 클래스를 변경할 수 있도록 설계.

 

회원 도메인/리포지토리 생성

  • 회원 객체(VO) 생성
  • 회원 리포지토리 인터페이스 생성
  • 회원 리포지토리 메모리 구현

 

회원 리포지토리 테스트 케이스 작성

  • JUnit이라는 프레임워크로 테스트
  • 동작하는지 보기위해 테스트케이스 작성
  • 테스트는 서로 의존관계가 없어야한다. 순서 상관없이 테스트가 되어야한다.

TDD(테스트주도개발) : 테스트를 먼저 만들고 구현 클래스를 만들어 돌려보는 것

 

 

회원 리포지토리 메모리 구현체 테스트

@AfterEach
public void afterEach(){
	repository.clearStore();
}
  • @AfterEach : 여러 테스트를 한꺼번에 실행 시, 메모리 DB에 직전 테스트의 결과가 남을 수 있다. @AfterEach 를 사용하여 각 테스트가 종료될 때 마다 메모리 DB에 저장된 데이터를 삭제한다.


회원 서비스 개발

private void validateDuplicateMember(Member member) {
	memberRepository.findByName(member.getName())
    .ifPresent(m -> {
    	throw new IllegalStateException("이미 존재하는 회원입니다.");
    });
 }
  • 람다 표현식
  • 인터페이스가 갖고 있는 메소드를 간편하게 즉흥적으로 구현해서 사용하는 것이 목적
  • (매개변수목록) -> { 함수몸체 }


회원서비스테스트

void 회원가입() {

	//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());
 }
  • 테스트코드는 한글 적어도 괜찮다.
  • given : 이런 상황이 주어져서 (이 데이터를 기반) then : 결과가 이렇게 나와야해
  • when : 이걸로 실행했을 때 (이걸 검증)
@BeforeEachpublic
void beforeEach() {
	memberRepository = new MemoryMemberRepository();
	memberService = new MemberService(memberRepository);
}
  • @BeforeEach : 각 테스트 실행 전에 호출. 테스트가 서로 영향이 없도록 항상 새로운 객체를 생성하고, 의존관계도 새로 맺어준다.


단축키(Windows)

ctrl+alt+v : 변수 선언할 때 사용
alt+enter : static import
ctrl +shift +t : 테스트코드 단축키
shift+f6 : 변수명 바꾸기
ctrl + shift + enter : 완료 후 줄바꿈

인프런 '스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술' 통해 학습 중.

'JAVA' 카테고리의 다른 글

Spring 핵심 01 : 객체 지향 설계와 스프링  (0) 2021.05.18
Spring 05 : AOP  (0) 2021.05.18
Spring 04 : 스프링 DB 접근  (0) 2021.05.18
Spring 03 : 스프링 빈과 의존관계  (0) 2021.05.18
Spring 01 : 프로젝트 환경설정  (0) 2021.05.18

Spring : 자바 플랫폼을 위한 오픈 소스 애플리케이션 프레임워크


Spring 환경설정

  • Java 11
  • IntelliJ

 

스프링 부트 생성

start.spring.io

  • Artifact : 결과물
  • Dependencies : 어떤 라이브러리를 가져다 쓸 것인지?

 

IntelliJ 프로젝트 생성

 

build.gradle 파일

  • maven / gradle 둘 다 main과 test 존재
  • test : test코드 (요즘 개발에서 test코드 매우 중요)

SpringBootApplication : 톰캣 내장함.

 

View 환경설정

  • resources/static/index.html
  • resources/templates/hello.html

 

Controller 설정

  • main/java/hello.hellospring/controller/HelloController.java

 

빌드 후 실행

gradlew.bat build cd build/libs java -jar hello-spring-0.0.1-SNAPSHOT.jar

  • mac에서는 ./gradlew build
  • 서버 배포 시 hello-spring-0.0.1-SNAPSHOT.jar 파일만 복사해서 넣고 java -jar hello-spring-0.0.1-SNAPSHOT.jar 실행. 이렇게 하면 서버에서도 스프링 동작 가능하다.

에러 2개 발생

1) 실행 시 에러

  • gradle을 통해서 실행됨에 따라 에러가 발생
  • 셋팅에서 바꿔줌.

 

2) 실행 후 localhost:8080 들어가면 에러페이지 떠야함.

  • 로그인 창이 뜸.
  • 오라클 DB와 톰캣이 충돌했을 때 나타나는 현상.
  • 오라클 관리자 사이트의 포트를 변경해야 함.

 

변경 후

 

인프런 '스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술' 통해 학습 중.

'JAVA' 카테고리의 다른 글

Spring 핵심 01 : 객체 지향 설계와 스프링  (0) 2021.05.18
Spring 05 : AOP  (0) 2021.05.18
Spring 04 : 스프링 DB 접근  (0) 2021.05.18
Spring 03 : 스프링 빈과 의존관계  (0) 2021.05.18
Spring02 : 예제(회원관리)  (0) 2021.05.18

+ Recent posts