1. vmware 설치

vmware 홈페이지에서 설치를 하려고 하면 해당 에러가 발생

 

https://softwareupdate.vmware.com/cds/vmw-desktop/player/17.5.2/23775571/windows/core/

 

CDS Repository - /var/www/public/stage/session-120/cds/vmw-desktop/player/17.5.2/23775571/windows/core

 

softwareupdate.vmware.com

해당 링크에서

다운로드

 

2. ubuntu 설치

1) 24.04 LTS 다운로드

https://ubuntu.com/download/desktop

대용량이다보니 파일 다운로드에 시간이 걸림

 

2) Create a New Virtual Machine 클릭

next

 

Browse 버튼 클릭후 다운받은 이미지 클릭

사용자 이름 패스워드는 개인이 알아서 설정해준다.

저장공간은 20GB면 충분하다.

 

입력한 사항들 확인하고 완료를 눌러준다.

설치완료

 

3. 우분투 환경설정

'보안 > linux' 카테고리의 다른 글

[명령어] apache2 서비스  (0) 2024.08.16
[명령어] 기본명령어  (0) 2024.08.16

$ service apache2 start 

아파치 서비스 시작

$ cd /var/www/html 

기본적인 html 페이지 경로 

이 경로에 페이지 추가하여 배포하면 됨

$ service apache2 stop

아파치 서비스 종료

$ service apache2 restart 

아파치 서비스 중지한 다음 시작 

$ service apache2 reload

아파치 서비스 다시시작, 다시 로드시 기본 아파치 프로세스는 하위 프로세스 종료하고 새 구성을 로드한 다음 새 하위 프로세스 시작함

$ service apache2 status

서비스 상태 표시

'보안 > linux' 카테고리의 다른 글

[vmware] ubuntu 설치  (0) 2024.08.22
[명령어] 기본명령어  (0) 2024.08.16

kali-linux : 기본이 debian으로 되어있어 명령어 형식이 debian 과 흡사

 

$ dpkg -l

깔려져있는 프로그램들의 형식 확인 가능

 

$ dpkg -l | grep z*

z로 시작하는 패키지 파일 포함 모든 패키지 파일들을 찾을 수 있음

$ dpkg -l | grep z

z가 포함된 패키지 파일들만 찾아볼 수 있음

 

$ dpkg -i [설치할 패키지명]

패키지 설치

 

$ dpkg -r [삭제할 프로그램명]

프로그램/패키지파일 삭제

 

$ mkdir [폴더명]

폴더생성

 

$ touch [ex.test.txt]

test라는 이름의 텍스트파일 생성

 

수정명령어

$ vi [ex.test.txt] 

$ vim [ex.test.txt] - vi에서 조금 더 향상됨

$ nano [ex.test.txt] 

$ nano -c [ex.test.txt] - 라인정보, 입력정보 등을 직관적으로 바로 확인하면서 작업가능

$ gedit [ex.test.txt] - 메모장과 같은 gui 환경에서 작업가능

 

nano -c
nano

[vim 모드]

- 명령모드 : 특정 기능 하는 명령어 입력하는 모드

- 입력모드 : 입력(i, insert)

- 마지막 행 모드 : 저장(w, write), 나가기(q, quit), 취소(!), 저장하지 않고 나가기(:q!)

✔︎마지막 행 모드인 이유 - :를 누를면 화면 맨 아래 커맨드 라인이 생기고 명령어를 치게끔 되기 때문

 

[사용자 전환] 

$ su - super user 권한 부여됨  => 패스워드 입력

$ exit - 이전 계정으로 복귀

$ whoami -현재 계정 정보 확인 

 

[파일 복사, 이동, 삭제]

$ cp [옵션] [복사할 디렉토리] [복사될 디렉토리]

[옵션]

-i  복사될 파일 이름이 이미 존재할 경우, 사용자에게 덮어 쓰기 여부를 물음

-b 복사될 파일 이름이 이미 존재할 경우, 백업파일을 생성

-f  복사될 파일 이름이 이미 존재할 경우, 강제로 덮어쓰기

-r  하위 디렉토리까지 모두 복사

-a 원본 파일의 속성, 링크 정보까지 모두 복사

-p 원본파일의 소유자, 그룹, 권한 등의 정보까지 모두 복사

-v 복사 진행 상태를 출력

-u 최신 파일이면 복사

$ mv [옵션] [이동할 파일] [이동될 위치]

-b 이동될 파일이 존재하면 백업파일을 만듦

-i  이동될 파일의 이름이 이미 존재할 경우, 사용자에게 덮어쓰기여부를 물음

-b 이동될 파일의 이름이 이미 존재할 경우, 백업파일을 생성

-f  이동될 파일의 이름이 이미 존재할 경우, 강제로 덮어씌움

-n  이동될 파일의 이름이 이미 존재할 경우, 덮어쓰기를 하지 않음

-r  하위 디렉토리까지 모두 이동

-v  이동 진행 상태를 출력

-u  원본파일이 복사본 파일보다 최신이거나 복사본 파일에 원본파일 및 디렉토리가 없을 경우 이동하는 옵션

$ rm [옵션] [삭제할 파일/디렉토리]

-f  강제로 파일이나 디렉토리를 삭제하고 대상이 없는 경우에는 메시지를 출력하지 않음

-r  디렉토리 내부의 모든 내용 삭제

-d 비어있는 디렉토리들만 삭제

-i  매번 삭제할때마다 사용자에게 삭제할 것인지 물음

-l  3개 이상의 파일을 삭제하거나 디렉토리 내부가 비어있지 않을때만 삭제할 것인지 물음

-v 삭제되는 대상의 정보를 출력

 

[디렉터리 목록 확인]

$ ls - 파일명만 확인

$ ls -l - 파일명 포함 상세정보 확인 가능

$ ll - ls -l과 같은 명령어

$ ls [디렉터리명] -lS(소문자L 대문자S) : 사이즈(큰수부터 작은수까지) 순서대로 나열

$ ls [디렉토리명] -ISr : 사이즈(작은수부터 큰 수까지) 순서대로 나열

$ ls -lt : 시간 최신 생성 파일부터 오래된순서대로 나열

$ ls -ltr : 시간 오래된것부터 최신 순으로 나열

 

[압축 명령어]

$ tar czf test.tar.gz test0*

test0으로 시작하는 모든 파일 test.tar.gz.tar로 압축됨

$ tar -cvf [파일명].tar [압축할파일1] [압축할파일2] [압축할폴더1] [압축할폴더2]

여러 디렉토리 및 파일들이 압축됨

 

[압축해제 명령어]

$ tar xzf [압축파일명]

압축해놓은 gzip 파일 압축해제

 

cvzf

zcvf

'보안 > linux' 카테고리의 다른 글

[vmware] ubuntu 설치  (0) 2024.08.22
[명령어] apache2 서비스  (0) 2024.08.16
  • next.js 
  • typescript
  • tailwind

파일구조 [src/app/]

  • board
    • boardCreate
    • boardDetail
    • boardList
    • boardUpdate

boardCreate

boardDetail

boardUpdate

  • components - 전체 공통적으로 사용하는 컴포넌트들
    • header.tsx
    • headrLogin.tsx
    • pagination.tsx
    • sidebar.tsx
  • main
    • home

  • manager
    • alarm
    • home
    • userInfo

  • mypage
    • mypageMain
    • mypageUpdate

  • user
    • login
    • register
    • userInfo
    • userInfoUpdate
     

 

  • video

화면 기록 2024-06-06 오후 7.14.40.mov
4.48MB

 

 

페이지구성

  • boardList - 게시판목록
  • boardCreate - 게시글작성
  • boardDetail - 게시글보기
  • boardUpdate - 게시글수정
  • boardDelete - 게시글삭제

 

 

[참고자료]

#Link 

https://wonit.tistory.com/357?category=829651

 

[정직하게 배워보는 Next js] 페이지를 연결하기 위한 Link-Component그리고 Pre-Fetch

해당 블로그 시리즈는 정직하게 배워보는 Next js 시리즈로써 총 8부작으로 이루어져 있습니다. Next.js공식 홈페이지에서 이야기하는 내용을 최대한 이해하기 쉽고 직관적이게 구성하였습니다. 0.

wonit.tistory.com

app.tsx index.tsx 사용할경우 link시키는

 

 

✔︎ 웹 애플리케이션과 싱글톤

 

 

✔︎ 스프링 컨테이너 생성

컨테이너에 등록된 빈 조회

hello.core.beanfind.ApplicationContextInfoTest.java

- 27줄에 ac.getBeandDefinition(beanDefinitionName) → bean에 대한 metadate 정보

- spring이 내부에서 사용하는 빈은 getRole()로 구분 가능 

  • ROLE_APPLICATION : 일반적으로 사용자가 정의한 빈
  • ROLE_INFRASTRUCTURE : 스프링이 내부에서 사용하는 빈

 

출력된 애플리케이션 빈

 

★ soutm → system.out.println 단축키 

 

✔︎ 스프링 빈 조회 - 기본

ApplicationContextBasicFindTest.java

- assertThat같은 경우는 검증하는것 

- asserThat의 경우 Assertions.assertThat에서 option+enter해서 on-demand로 Assertions를 없앰 (줄임말)

- 항상 test를 할때는 실패 test도 있어야해서 빈 이름으로 조회X test도 진행함

- 마지막 빈 이름으로 조회X부분에서는 () -> 뒷부분의 로직을 실행했을때 앞의 예외가 던져져야 함 

 

✔︎ 스프링 빈 조회 - 동일한 타입이 둘 이상부터 시작 

ApplicationContextSameBeanFindTest.java

package hello.core.beanfind;

import hello.core.member.MemberRepository;
import hello.core.member.MemoryMemberRepository;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Map;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

public class ApplicationContextSameBeanFindTest {
    AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SameBeanConfig.class);

    @Test
    @DisplayName("타입으로 조회시 같은 타입이 둘 이상 있으면, 중복 오류가 발생한다")
    void findBeanByTypeDuplicate(){
//        MemberRepository bean = ac.getBean(MemberRepository.class);
        assertThrows(NoUniqueBeanDefinitionException.class, () -> ac.getBean(MemberRepository.class));

    }

    @Test
    @DisplayName("타입으로 조회시 같은 타입이 둘 이상 있으면, 빈 이름을 지정하면 된다")
    void findBeanByName(){
        MemberRepository memberRepository = ac.getBean("memberRepository1", MemberRepository.class);
        assertThat(memberRepository).isInstanceOf(MemberRepository.class);
    }

    @Test
    @DisplayName("특정 타입을 모두 조회하기")
    void findAllBeanByType(){
        Map<String, MemberRepository> beansOfType = ac.getBeansOfType(MemberRepository.class);
        for(String key : beansOfType.keySet()){
            System.out.println("key = " + key + " value = " + beansOfType.get(key));
        }
        System.out.println("beansOfType = " + beansOfType);
        assertThat(beansOfType.size()).isEqualTo(2);
    }

    @Configuration
    static class SameBeanConfig{
        @Bean
        public MemberRepository memberRepository1(){
            return new MemoryMemberRepository();
        }

        @Bean
        public MemberRepository memberRepository2(){
            return new MemoryMemberRepository();
        }

    }

}

- getBean에서 option+command+v  → 앞부분 자동완성 

★ command + shifht + enter → 자동 세미콜론 생성

 

✔︎ 스프링 빈 조회 - 상속 관계

ApplicationContextExtendsFindTest.java

package hello.core.beanfind;

import hello.core.discount.DiscountPolicy;
import hello.core.discount.FixDiscountPolicy;
import hello.core.discount.RateDiscountPolicy;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Map;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;

public class ApplicationContextExtendsFindTest {
    AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(TestConfig.class);

    @Test
    @DisplayName("부모 타입으로 조회시, 자식이 둘 이상 있으면, 중복 오류가 발생한다")
    void findBeanByParentTypeDuplicate(){
//        DiscountPolicy bean = ac.getBean(DiscountPolicy.class);
        assertThrows(NoUniqueBeanDefinitionException.class, () -> ac.getBean(DiscountPolicy.class));
    }

    @Test
    @DisplayName("부모 타입으로 조회시, 자식이 둘 이상 있으면, 빈 이름을 지정하면 된다")
    void findBeanByParentTypeBeanName(){
        DiscountPolicy rateDiscountPolicy = ac.getBean("rateDiscountPolicy", DiscountPolicy.class);
        assertThat(rateDiscountPolicy).isInstanceOf(RateDiscountPolicy.class);
    }

    @Test
    @DisplayName("특정 하위 타입으로 조회")
    void findBeanBySubType(){
        RateDiscountPolicy bean = ac.getBean(RateDiscountPolicy.class);
        assertThat(bean).isInstanceOf(RateDiscountPolicy.class);
    }

    @Test
    @DisplayName("부모 타입으로 모두 조회하기")
    void findAllBeanByParentType(){
        Map<String, DiscountPolicy> beansOfType = ac.getBeansOfType(DiscountPolicy.class);
//        beansOfType의 사이즈가 2개면 성공
        assertThat(beansOfType.size()).isEqualTo(2);
        for (String key : beansOfType.keySet()){
            System.out.println("key = " + key + " value = " + beansOfType.get(key));
        }
    }

    @Test
    @DisplayName("부모 타입으로 모두 조회하기 - Object")
    void findAllBeanByObjectType(){
        Map<String, Object> beansOfType = ac.getBeansOfType(Object.class);
        for(String key : beansOfType.keySet()){
            System.out.println("key = " + key + " value = " + beansOfType.get(key));
        }
    }

    @Configuration
    static class TestConfig{
        @Bean
        public DiscountPolicy rateDiscountPolicy(){
            return new RateDiscountPolicy();
        }

        @Bean
        public DiscountPolicy fixDiscountPolicy(){
            return new FixDiscountPolicy();
        }
    }
}

 

✔︎ BeanFactory와 ApplicationContext

- BeanFactory

  • 스프링 컨테이너의 최상위 인터페이스
  • 스프링 빈을 관리하고 조회하는 역할 담당
  • getBean() 제공
  • 대부분의 기능을 제공

- ApplicationContext

  • BeanFactory 기능을 모두 상속받아서 제공
  • BeanFactory + 부가기능

➜ 결론

- ApplicationContext는 빈 관리기능 + 편리한 부가기능 제공

- BeanFactory나 ApplicationContext를 스프링 컨테이너라고 부름

 

✔︎ 다양한 설정 형식 지원 - 자바 코드, XML

XmlAppContext.java

- GenericXml ← xml이라는 문서를 설정정보로 사용

 

src/main/resources/appConfig.xml

- new-xml configuration file-spring config 에서 파일 생성

- <bean></bean> 빈 등록

 

✔︎ 스프링 빈 설정 메타 정보 - BeanDefinition

- BeanDefinition 

  • 역할과 구현을 개념적으로 나눈 것
  • xml이나 자바 코드를 읽어서 BeanDefinition을 만들 수 있음
  • 스프링 컨테이너가 자바코드인지 xml인지에 상관없이 BeanDefinition만 알면 됨
  • 스프링 컨테이너는 이 메타정보를 기반으로 스프링 빈을 생성 

BeanDefinitionTest.java

'개발 > spring' 카테고리의 다른 글

[스프링] 싱글톤 컨테이너  (0) 2024.04.26
[스프링] 스프링 핵심 원리 - 기본편 2  (0) 2023.11.27
[스프링] 스프링 핵심 원리 - 기본편 1  (0) 2023.11.27
[스프링] start  (0) 2023.11.06

✔︎권장사항

- java 11

- IntelliJ

 

✔︎스프링부트 스타터에서 프젝 생성

https://start.spring.io/

 

시작하려고보니 자바 버전이 21 17밖에 없어서 버전을 먼저 맞추려고 한다.

 

✔︎설치되어 있는 모든 자바 버전 확인 

$ /usr/libexec/java_home -V

17이상이 없어서 업그레이드 해줘야 될 것 같음

✔︎java17 설치

https://www.oracle.com/java/technologies/downloads/#jdk17-mac

인텔이라 가장 아래거로 설치
설치 완

버전 확인 

$ java -version

 

✔︎프로젝트 생성 

 

✔︎파일구조 

기본일때
Compact일때

Compact패키지일때는 hello.core의 hello 폴더에 뭘 생성하기 어렵다고함  

 

인터페이스와 구현체를 같은 패키지에 두는 것보다는 따로 두는게 설계상 좋음

 

세번째 줄 MemberRepository에서 opt+enter 해줘서 얘네 생김

★자동완성

세미콜론까지 자동완성 시켜주는 단축키 : Command + Shift + Enter

public state void main 자동완성 : psvm

getter/setter 자동완성 : command + N

System.out.println 자동완성 : sout

 

이 상태에서 Member 쪽에 대고 command+option+v하면
이렇게 바뀜

✔︎return으로 주문결과 반환

src/main/java/hello.core/order/OrderService.java

 

src/main/java/hello.core/order/OrderApp.java

주문 도메인 전체에 대한 구현 완료

정액 할인 정책을 정률로 바꾸었을 때 클라이언트에 영향을 주지 않는지 역할이 잘 분리되었는지 확인 해볼 예정임

 

 


객체 지향 원리 적용

✔︎ 새로운 할인 정책 개발

core.discount.DiscountPolicy

package hello.core.discount;

import hello.core.member.Member;

public interface DiscountPolicy {

//    @return 할인 대상 금액
    int discount(Member member, int price);
}


core.discount.FixDiscountPolicy

package hello.core.discount;

import hello.core.member.Grade;
import hello.core.member.Member;

public class FixDiscountPolicy implements DiscountPolicy{

    private int discountFixAmount = 1000; //1000원 할인
    //VIP일경우 1000원 할인 아니면 할인x
    @Override
    public int discount(Member member, int price) {
        if (member.getGrade() == Grade.VIP){
            return discountFixAmount;
        } else {
        return 0;
        }
    }
}


core.discount.RateDiscountPolicy

package hello.core.discount;

import hello.core.member.Grade;
import hello.core.member.Member;

public class RateDiscountPolicy implements DiscountPolicy{

    private int discountPercent = 10;

    @Override
    public int discount(Member member, int price) {
        if(member.getGrade() == Grade.VIP){ //멤버등급이 vip일 경우
            return price * discountPercent / 100;
        } else {
            return 0;
        }
    }
}

 

✔︎ 새로운 할인 정책 적용과 문제점

- 적용시키기 위해서는 order.OrderServiceImpl 에서 적용시켜야함

 

order.OrderServiceImpl

- FixDiscountPolicy를 RateDiscountPolicy로 바꿔주어야 함 

package hello.core.order;

import hello.core.discount.DiscountPolicy;
import hello.core.discount.FixDiscountPolicy;
import hello.core.discount.RateDiscountPolicy;
import hello.core.member.Member;
import hello.core.member.MemberRepository;
import hello.core.member.MemoryMemberrepository;

public class OrderServiceImpl implements OrderService{

    private final MemberRepository memberRepository = new MemoryMemberrepository();
    //private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
    private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
    @Override
    public Order createOrder(Long memberId, String itemName, int itemPrice) {
        //member 찾음
        Member member = memberRepository.findById(memberId);
        //단일책임의 원칙 잘 지켜짐 할인정책에 문제가 있을때 할인정책만 수정 가능
        int discountPrice = discountPolicy.discount(member, itemPrice);

        return new Order(memberId, itemName, itemPrice, discountPrice);
    }
}

 

- 할인정책을 변경하기 위해서는 클라이언트인 OrderServiceImpl

단순히 DiscountPolicy에만 의존을 하고 있다고 알고 있었지만

OrderServiceImpl에서는 DiscountPolicy 뿐만 아니라 FixDiscountPolicy인 구체 클래스도 함께 의존하고 있다. → DIP 위반

#DIP(Dependency Inversion Principle) : 저수준 모듈이 고수준 모듈에 의존하게 되는 것

맞추기 위해서는 추상에만 의존하도록 변경해야함 (인터페이스에 의존)

 

기존의 이 코드에서 아래처럼 바꿔주어야 함

➜ 인터페이스에만 의존하도록 설계와 코드를 변경함

 

 

✔︎ 관심사의 분리

생성자를 만들어줌
여기서 MemberRepository는 추상화에만 의존 &rarr; DIP를 지키게 됨

AppConfig는 생성한 객체 인스턴스의 참조(레퍼런스)를  생성자를 통해서 주입(연결)해준다.

 

- 설계 변경으로 `MemberServiceImpl` `MemoryMemberRepository` 를 의존하지 않는다! 단지 `MemberRepository` 인터페이스만 의존한다.

- MemberServiceImpl` 입장에서 생성자를 통해 어떤 구현 객체가 들어올지(주입될지)는 알 수 없다.

- MemberServiceImpl` 의 생성자를 통해서 어떤 구현 객체를 주입할지는 오직 외부( `AppConfig` )에서 결정된 다.

- MemberServiceImpl` 은 이제부터 **의존관계에 대한 고민은 외부**에 맡기고 **실행에만 집중**하면 된다.

 

core.MemberServiceImpl 기존의 이코드에서  

package hello.core.member;
//회원 서비스 구현체
public class MemberServiceImpl implements MemberService{

    //가입하고 찾으려면 memory레포가 있어야함 구현객체를 MemoryMemberRepository로 선택
    private final MemberRepository memberRepository = new MemoryMemberrepository(); //2. 여기서 할당이 됨
    //join에서 save를 호출하면 다형성에 의해서 Memory레포에 있는 save(오버라이드한개)가 호출됨
    public MemberServiceImpl(MemberRepository memberRepository){    //1. 여기서 memorymemberReposiotry가 들어와서
        this.memberRepository = memberRepository;
    }
    @Override
    public void join(Member member) {
        memberRepository.save(member);
    }

    @Override
    public Member findMember(Long memberId) {
        return memberRepository.findById(memberId);
    }
}

 이걸로 변경

package hello.core.member;
//회원 서비스 구현체
public class MemberServiceImpl implements MemberService{

    //가입하고 찾으려면 memory레포가 있어야함 구현객체를 MemoryMemberRepository로 선택
    private final MemberRepository memberRepository;
    //join에서 save를 호출하면 다형성에 의해서 Memory레포에 있는 save(오버라이드한개)가 호출됨
    public MemberServiceImpl(MemberRepository memberRepository){    //1. 여기서 memorymemberReposiotry가 들어와서
        this.memberRepository = memberRepository;
    }
    @Override
    public void join(Member member) {
        memberRepository.save(member);
    }

    @Override
    public Member findMember(Long memberId) {
        return memberRepository.findById(memberId);
    }
}

 

✔︎AppConfig 리팩터링

method명을 가지고옴으로써 역할이 다 드러남

→ 할인 정책을 변경해도 Appconfig 변경만으로 적용가능

 

 

스프링 컨테이너 적용

 

MemberApp.java

 

OrderApp.java

 

AppConfig.java

'개발 > spring' 카테고리의 다른 글

[스프링] 싱글톤 컨테이너  (0) 2024.04.26
[스프링] 스프링 컨테이너와 스프링 빈  (0) 2024.04.25
[스프링] 스프링 핵심 원리 - 기본편 1  (0) 2023.11.27
[스프링] start  (0) 2023.11.06

인프런 스프링 핵심 원리 -기본편 강의 샀다. 시작한다.

'개발 > spring' 카테고리의 다른 글

[스프링] 싱글톤 컨테이너  (0) 2024.04.26
[스프링] 스프링 컨테이너와 스프링 빈  (0) 2024.04.25
[스프링] 스프링 핵심 원리 - 기본편 2  (0) 2023.11.27
[스프링] start  (0) 2023.11.06

+ Recent posts