[2023.01.02] 개발자 교육 70일 차 : 강의-Spring Boot 실습 [구디 아카데미]

DaramGee·2024년 1월 2일
0

복습

스프링 부트 스타터!

✅ 스프링 프로젝트에서 설정해야할 의존성을 사전에 조합하여 제공된다. 즉, 의존성 설정을 보다 쉽게 할 수 있다.


  • 의존성 자동처리(의존성 전이도 자동으로 처리)

  • 의존성 상속관계(전이)도 스타터에선 자동으로 정리해줌.

  • starter버전과 boot버전은 맞추어 줘야 한다

  • ![[Pasted image 20231226094509.png]]

  • configuration 목록

  • ompileOnly: 컴파일 타임에만 의존성을 주입한다.

  • runtimeOnly: 런타임에만 의존성을 주입한다. (deprecated: runtime)

  • implementation: 컴파일 타임과 런타임에 모두 쓰이는 의존성을 주입한다. (deprecated: compile)

  • annotationProcessor: 어노테이션 프로세서로써 컴파일 시 사용되는 의존성을 주입한다.

  • testImplementation: 테스트 시에만 의존성을 주입한다. (deprecated: testCompile)

  • 의존성은 그룹명:이름:버전 순으로 명시해서 주입할 수 있으며, 버전명은 optional로, 꼭 명시하지 않아도 된다.

  • 설정의 자동화

  • @SpringBootApplication - Spring Boot Application의 시작 클래스에 붙인다

  • @SpringBootApplication = @Configuration + @EnableAutoConfiguration + ComponentScan@Configuration -자바 설정 클래스(xml로설정, 자바클래스 설정방법)

  • @ComponentScan - 자동빈 스캔할 때

  • @EnableAutoConfiguration - 자동 설정 가능 - 스프링부트 자동으로 빈등록 ->  @AutoConfigurationPackage -> @Import({Register.class})

  • 자바설정 파일 클래스 -> @Import({AutoConfigurationImportSelector.class}):선택적으로 결정Starter - 라이브러리를 패키지로 자동결정해줌

  • @EnableAutoConfiguration - 빈설정을 자동으로 결정


viewModel

✅ Model 클래스는 애플리케이션의 비즈니스 로직이나 데이터를 가지고 있으며, 이를 뷰에 전달하여 사용자에게 보여지도록 합니다.


  • 데이터의 영속성을 활용한 결과값들은 viewModel에 꼭 필요하다. (클래스 이름 추가 시)

  • 문자열 출력이 아닌 화면 출력을 하는 @Controller 사용 클래스의 UI 사용을 위해서 Model과 @RequestParam을 사용한다

  • 클래스 이름 추가할 때 화면(table : 로우 + 컬럼)과 데이터는 밀접한 관계가 있다.

  • MVVM 디자인 패턴


강의 내용

AOP(792P)

✅ Spring AOP (Aspect-Oriented Programming) 는 공통 관심사를 분리하여 관리하는 프로그래밍 접근방법이다.(관점지향프로그래밍 지원 기술)


  • 메소드 안의 기능을 핵심기능, 부가기능으로 나누었을 때, 부가기능을 공통된 하나의 장소에 모아서 관리하는 방식이 AOP 방식이다.

  • 부가기능 : 보안, 로깅(사용자 접속내용 기록), [[트랜잭션]]관리(커밋, 롤백)

  • 수평적 관점(횡단 관심사 cross-cutting concerns): 동등한 관점

  • 예시 설명: 예를 들어, 프로그램에 로깅 기능이 필요한데 이를 모든 코드에 반복해서 작성하는 대신, AOP를 사용하여 로깅 기능을 한 곳에서 관리하고 다른 코드에 적용할 수 있습니다.

  • <->[[OOP]]가 객체를 중심으로 데이터와 기능을 구성한다면, AOP는 부가기능(advice)을 동적으로 추가해주는 기술이 필요하였다. (공통된 관심사)


  • 관련 용어

  • target : advice(부가기능)가 추가될, 필요한 객체(반복되는 코드가 들어있어서 분리가 필요한 클래스)
  • advice(부가기능) : target에 동적으로 추가될 기능 -> 따라서 어노테이션 제공됨
  • joinpoint : advice가 추가(join)될 대상이 되는 메소드
  • pointcut : joinpoint를 정의한 패턴-정규식(pointcut execution), 간섭을 하겠다고 표시!!(일괄처리, 자동)
java.util.regex.*

execution(* com.example.demo.*Logic.cud*(..))
어떤 반환타입이든지/패키지명/Logic으로 끝나는 클래스/cud로 시작하는 메소드들/매개변수 상관없음
예 : cudEmp, cudBoard, cudNotice(o) / getBoardList, getNoticeList(x)

@Around("execution(* com.example.*.*(..))")
  • proxy : 스프링에서 aop를 자동으로 설정하기 위해 필요

  • 관련 어노테이션

  • @Around : 메소드 시작, 끝부분 모두 감쌈(around advice)
  • @Before : 메소드 시작 부분(before advice)
  • @After : 메소드 끝부분(after advice)
advice 공통 부가기능 담은 클래스 생성 후 아래와 같은 메소드에 전, 후 설정 및 출력을 할 수 있음.
//@Transational  
public List<Map<String, Object>> memberList(Map<String, Object> rmap) {  
    //before advice con.setAutoCommit(false);  
    logger.info("Dao-memberList");  
    List<Map<String, Object>> mList = null;  
    mList = sqlSessionTemplate.selectList("memberList", rmap);  
    //after advice con.commit();  
    //con.SetAutoCommit(true);    return mList;  
}

[!quote] 메소드 안의 기능을 핵심기능, 부가기능으로 나누었을 때, 부가기능을 공통된 하나의 장소에 모아서 관리하는 방식이 AOP 방식이다.

  • 스프링 프로젝트 생성(aopdemo)

  • 뷰 -> 커맨드 팔레트 -> spring initializr -> 3.1.7 -> 기본값->spring dev tool, web, lobmoc

  • 실습 1 - 클래스명, 메소드명에 따른 부가기능 실행

  • 부가기능을 공통코드로 추가할 때, 중간지점은 약속하기 어려우니 코드의 앞 혹은 뒤에 배치하는 것이 가능

  • SomeClass(반복되는 코드가 그대로 구현되어있는 클래스)

  • AnyClass(target 관심사를 분리헤 적용할 클래스)
    - 부가기능 적용(m으로 시작) : methodA, methodB,
    - 부가기능 적용 x : others

  • AnyAdvice(pointcut 관심사 분리를 위해 설계한 구현체 클래스-정규식 표현식 사용-m으로 시작하는 메소드)
    - target이 되는 AnyClass 에 m으로 시작하는 메소드가 있다면 그 앞과 뒤에 공통코드를 넣도록 설계함으로서 관점지향 프로그래밍에 대해 이해해보자!

  • AnyMain(메소드 이름 같으면 처리하는 실행 여부 확인하는 클래스)

package com.example.aopdemo;  
  
import java.lang.reflect.Method;  
  
public class AnyMain {  
    public static void main(String[] args) throws Exception{  
        Class<?> myClass = Class.forName("com.example.aopdemo.AnyClass");  
        Object obj = myClass.newInstance();  
  
        AnyAdvice anyAdvice = new AnyAdvice();  
  
        for(Method m:myClass.getDeclaredMethods()){  
            anyAdvice.invoke(m,obj,null);  
        }  
    }  
}
  • 실습 2 - @Transational 여부에 따른 부가기능 실행

  • TransMain.java : 메소드 정의, 어드바이스 정의, 일부 메소드만 @Transational 표시 -> 부가기능 실행
    - methodA에만 부가기능으로 넣어둔 로그 부분이 구현되어 들어가는 결과값 확인 가능
@Transactional  
public void methodA(){  
    System.out.println("methodA 처리 구현");  
}  
public void methodB(){  
    System.out.println("methodB 처리 구현");  
}  
public void others(){  
    System.out.println("others 처리 구현");  
}
  • 실습3 - 프록시 설정, AOP 자동설정, 클래스, 메소드명에 따른 부가기능 실행

  • LogApplication.java : 메소드 정의, 어드바이스 정의, cud로 시작하는 메소드만 기능 실행
  • @EnableAspectJAutoProxy //AOP 자동설정 되는 어노테이션
  • @Aspect //해당 클래스를 Aspect로 사용하겠다는 것을 명시
  • @Around //메소드 앞/메소드 뒤 실행 :
@Component  
@Aspect  // 해당 클래스를 Aspect로 사용하겠다는 것을 명시
class LoggingAdvice {  
	//대상 “메서드” 실행 전, 후 또는 예외 발생 시에 Advice를 실행
    @Around("execution(* com.example.aopdemo.*Target.cud*(..))")  
    public Object logMethod(ProceedingJoinPoint pj) throws Throwable {  
        //시작되는 공통코드 - 부가기능 로깅(시작 : 시작시간, 끝 : 결과값 & 처리시간)  
        // (핵심기능은 AvyTarget의 메소드임)  
        //시작시간 계산  
        long start = System.currentTimeMillis();  
        System.out.println("{{start}}" + pj.getSignature().getName()  
                + Arrays.toString(pj.getArgs()));  
        Object result = pj.proceed();//AnyTarget 처리메소드(핵심기능) 호출  
        //끝부분 추가 공통코드 - AnyTarget 끝부분에 추가될 코드  
        System.out.println("account: "+ result);  
        //현재시간 - 스타트 시간 : 실행(처리)시간을 로그에 찍기  
        System.out.println("{{end}}" + (System.currentTimeMillis()-start)+"ms");  
        return result;  
    }  
}


회원관리 메뉴 추가(CRUD 복습)

  • 상태관리(쿠키 & 세션)

  • 관련 어노테이션

  • 게시판 구현(솔루션화 고려 설계) -> 통합게시판

  • 테이블 설계 분리(조인, 트랜잭션)

  • 작성자 인증(세션으로부터 자동입력)
    - 어떤 값을 세션에 담을까?
    - 어떤 값을 쿠키에 담을까?
    - 리액트로 화면을 처리할 때 세션이 지원되지 않는다?

  • 댓글 처리를 구현해 본다면?
    - 원글 & 댓글 & DB 설계에 어떻게 그려져야 하는가?
    - 상세보기 1건, 댓글 n건

  public List<Map<String, Object>> memberDetail(Map<String, Object> rmap) {  
        logger.info("Logic-memberList");  
        List<Map<String, Object>> mList = null;  
        mList = memberDao.memberList(rmap);  
   //   게시글 & 댓글 입력을 위한 코드 구성  
        List<Map<String, Object>> cList = null;        
        Map<String,Object> rmap = new HashMap<>();        
        cList = memberDao.commentList(rmap);        
        rmap.put(1,cList);        
        mList.add(rmap);
        return mList;
        }
  }
  • 첨부파일 지원하는 API는 무엇이 있고, 환경설정에 어떤 것이 필요할까?
    - 외부라이브러리(이미지 처리, 첨부파일 처리 코드 -> 공통코드화) - quill 등
    - 클라우드스토리지(사진서비스 제공 -> 동기화 가능) -
    - RDBMS 외 NoSQL 함께 사용(Realtime database 강점-코드로 동기화 처리) - Firebase

공통코드 작성 시 필요 어노테이션

  • @Configuration : 공통코드, 설정내용 담은 클래스(클래스 앞)
  • @Component : 사용자 정의 빈을 확인하여 이른 주입 가능(클래스 앞)
  • @Transactional(메소드 앞)

소제목

  • demo외 폴더 접근해야하는 경우

  • RootConfig.java에 다른 경로에서도 컴포넌트 스캔을 사용하는 것을 설정하면 demo 외 폴더의 실행도 가능
  • java 폴더 하위에 pk 폴더의 패키지도 루트에 등록하여 스캔할 컴포넌트로 지정해둔다면, 해당 패키지의 클래스도 빈에 등록되어 스프링에서 사용이 가능해진다.
package com.example.demo.step1;  
  
import org.springframework.context.annotation.ComponentScan;  
import org.springframework.context.annotation.Configuration;  
  
@Configuration  
@ComponentScan(basePackages = {"pk.gym.controller"})  
@ComponentScan(basePackages = {"pk.gym.logic"})  
@ComponentScan(basePackages = {"pk.gym.dao"})  
@ComponentScan(basePackages = {"pk.gym.config"})  
public class RootConfig {  
  
}

0개의 댓글