SRP 단일 책임 원칙 (Single Responsibility principle)

한 클래스는 하나의 책임만 가져야 한다.

하나의 책임이라는 것은 모호하다.

클 수 있고, 작을 수 있다.

문맥과 상황에 따라 다르다.

중요한 기준은 변경이다. 변경이 있을 때 파급 효과가 적으면 단일 책임 원칙을 잘 따른 것

예) UI변경, 객체의 생성과 사용을 분리

 

OCP 개방-폐쇄 원칙 (Open/closed principle)

소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다

이런 거짓말 같은 말이? 확장을 하려면, 당연히 기존 코드를 변경?

다형성을 활용해보자

인터페이스를 구현한 새로운 클래스를 하나 만들어서 새로운 기능을 구현

지금까지 배운 구현의 분리를 생각해보자

 

LSP 리스코프 치환 원칙 (Liskov substitution principle)

프로그램의 객체는 프로그램의 정확성을 깨트리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다

다형성에서 하위 클래스는 인터페이스 규약을 다 지켜야 한다는 것, 다형성을 지원하기 위한 원칙, 인터페이스를 구현한 구현체는 믿고 사용하려면, 이 원칙이 필요하다

단순히 컴파일에 성공하는 것을 넘어서는 이야기

예) 자동차 인터페이스의 엑셀은 앞으로 가라는 기능, 뒤로 가게 구현하면 LSP 위반, 느리더라도 앞으로 가야함

 

ISP 인터페이스 분리 원칙 (Interface segregation principle)

특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다

자동차 인터페이스 -> 운전 인터페이스, 정비 인터페이스로 분리

사용자 클라이언트 -> 운전자 클라이언트, 정비사 클라이언트로 분리

분리하면 정비 인터페이스 자체가 변해도 운전자 클라이언트에 영향을 주지 않음

인터페이스가 명확해지고, 대체 가능성이 높아진다.

 

DIP 의존관계 역전 원칙 (Dependency inversion principle)

프로그래머는 "추상화에 의존해야지, 구체화에 의존하면 안된다." 의존성 주입은 이 원칙을 따르는 방법 중 하나다.

쉽게 이야기해서 구현 클래스에 의존하지 말고, 인터페이스에 의존하라는 뜻

앞에서 이야기한 역할(Role)에 의존하게 해야 한다는 것과 같다. 객체 세상도 클라이언트가 인터페이스에 의존해야 유연하게 구현체를 변경할 수 있다! 구현체에 의존하게 되면 변경이 아주 어려워진다.

 

 

정적 컨텐츠, MVC와 템플릿 엔진, API 이 3가지는 웹 개발에서 가장 중요한 기초라고 볼 수 있습니다.

개발을 하게 된다면 필수적으로 알아야 하는 내용이므로 작성하였습니다.

 

1. 정적 컨텐츠

파일을 그대로 클라이언트에게 전달하는 것

Static Content

By default, Spring Boot serves static content from a directory called /static (or /public or /resources or /META-INF/resources) in the classpath. It uses the ResourceWebHandler from Spring WebFlux so that you can modify that behavior by adding your own WebFluxConfigurer and overriding the addResourceHandlers method.

정적 콘텐츠
기본적으로 스프링 부트는 클래스 경로에 있는 /static(또는 /public 또는 /resources 또는 /META-INF/resources) 디렉토리의 정적 콘텐츠를 제공합니다. 스프링 웹플럭스의 ResourceWebHandler를 사용하여 자신만의 WebFluxConfigurer를 추가하고 addResourceHandler 메서드를 재정의하여 해당 동작을 수정할 수 있습니다.

 

2. MVC와 템플릿 엔진

서버에서 변형된 파일을 클라이언트에게 전달하는 것

MVC: Model, View, Controller

 

내장 톰캣 서버는 웹브라우저의 요청을 받아 스프링 컨테이너에 매핑되어있는 컨트롤러를 통해 메서드를 호출합니다

이때 Model에는 전달할 데이터를 key, value 형태로 값을 담아 리턴값(hello-template)으로 문자를 반환하면 viewResolver가 화면을 찾아서 처리합니다

viewResolver는 view를 찾아주고 템플릿 엔진을 연결해주는 역할을 합니다 ( ex) template/hello-template.html )

Thymeleaf 템플릿 엔진 처리를 통해 렌더링 된 파일을 클라이언트에게 반환합니다

 

스프링 부트 템플릿엔진 기본 viewName 매핑

`resources:templates/`+{ViewName}+`.html`

 

3. API

JSON 데이터 포맷 형태로 클라이언트에게 전달 하는 것

 

@ResponseBody  사용 - Http 통신 프로토콜의 Body에 문자 내용을 직접 반환

`viewResolver` 대신에 `HttpMessageConverter` 동작

기본 문자처리(StringConverter): `StringHttpMessageConverter`

기본 객체처리(JsonConverter): `MappingJackson2HttpMessageConverter`

byte 처리 등등 기타 여러 HttpMessageConverter 기본으로 등록되어 있음

 

참고: 클라이언트의 HTTP Accept 해더와 서버의 컨트롤러 반환 타입 정보 둘을 조합해서 `HttpMessageConverter` 선택된다.

 

'Java' 카테고리의 다른 글

Math 관련 내장함수  (0) 2024.11.13
Array 관련 내장함수  (1) 2024.11.10
String 관련 내장함수  (0) 2024.11.08
디자인 패턴(Design Pattern)  (0) 2024.11.05
Java introduction  (7) 2024.11.04

환경변수 설정 (Linux)

1. Java 실행 파일 위치 확인 (심볼릭 링크 위치)

which java

일반적으로 /usr/bin/java와 같이 나옵니다.

 

2. 실제 Java 설치 경로 확인

readlink -f $(which java)

이 명령은 java 실행 파일의 심볼릭 링크가 가리키는 실제 경로를 출력합니다.

예를 들어 /usr/lib/jvm/java-11-openjdk-amd64/bin/java와 같은 경로가 나옵니다.

 

... 작성중

 

컴파일

Hello.java (소스파일) -> Hello.class (클래스파일 == 바이너리(이진) 파일)

1. javac Hello.java - (컴파일러인 javac가 Hello.java 파일을 읽어서 jvm이 알아들을 수 있는 기계어로 변환)

2. java Hello - (자바 인터프리터(java)를 이용해 자바 프로그램(클래스 파일) 을 실행)

 

빌드

우리가 만든 소스코드들(.java)를

컴퓨터에서 이해할 수 있는 바이너리코드(.class)로 변환

기계가 바로 읽고 실행할 수 있는

압축된 파일(jar 또는 war)로 패키징

 

./gradlew build --console=plain

> Task :compileJava UP-TO-DATE          - 컴파일
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :resolveMainClassName UP-TO-DATE
> Task :bootJar UP-TO-DATE              - jar파일
> Task :jar UP-TO-DATE                  - plain-jar파일
> Task :assemble UP-TO-DATE
> Task :compileTestJava UP-TO-DATE
> Task :processTestResources NO-SOURCE
> Task :testClasses UP-TO-DATE
> Task :test UP-TO-DATE                 - 테스트
> Task :check UP-TO-DATE
> Task :build UP-TO-DATE                - 모든 작업의 결과물을 build디렉토리에 저장

BUILD SUCCESSFUL in 680ms
7 actionable tasks: 7 up-to-date

 

(plain)jar - jar

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

.class 파일들과 해당 클래스에서 사용되는 리소스(이미지 등)등 포함

외부 라이브러리를 포함하지 않음

주로 다른 프로젝트에 종속성으로 사용될 때 사용

또는 로컬 환경에서 실행되는 어플리케이션으로 사용(*클래스패스 추가)

 

(Runnable)jar - bootJar

.class 파일들과 정적 자원(HTML, CSS, JavaScript, 이미지파일),

웹 애플리케이션이 의존하는 라이브러리나외부 모듈(프레임워크 라이브러리, DB드라이버) 등 포함

내장형 서버(톰캣)을 포함시켜 웹 프로젝트를 압축한 파일

외부 웹서버 없이 웹프로젝트를 단독으로 실행, 배포 가능


war

JAVA 웹 프로젝트를 압축한 파일

이 파일을 실행하려면, 웹 애플리케이션 서버(WAS)가 필요함   ex) Apache Tomcat

웹 애플리케이션을 통째로 패키징 하고 배포하기 위한 목적으로 사용

 

스프링 부트에서 가이드하는 표준 형식은 jar

:외부에 별도의 서버 설치없이 단독으로 웹 어플리케이션 실행이 가능.

하지만, 내장된 서블릿 컨테이너는 JSP를 실행할 수 없다.

(JSP 엔진을 내부적으로 가지고 있지 않기 때문에)

 

war 사용시기

jsp를 사용하여 화면을 구성해야한다.

외장 was를 이용할 계획이다.

 

빌드의 결과물

jar과 war 파일이란?

프로젝트의 내용을 압축해 담아놓은 파일

 

jar과 war 파일을 왜 만들까?

웹 프로젝트를 폴더 째로 전해 줄 수 없으니,

컴퓨터가 읽을 수 있는 형태의 파일을 전달하기 위해서

 

배포란?

완성된 실행 가능한 파일(jar, war)을

사용자가 접근할 수 있는 환경에 배치하고 실행하는 것

(이후 모니터링, 유지보수도 포함)

 

빌드하고 실행하기

콘솔로 이동
1. `./gradlew build`
2. `cd build/libs`
3. `nohup java -jar hello-spring-0.0.1-SNAPSHOT.jar &`
4. 실행 확인
 

재빌드 시 build 디렉토리 삭제 후 재 생성
./gradlew clean build

 

nohup 과 &

  nohup &(백그라운드 실행)
목적 터미널이 종료된 후에도
프로그램이 실행해야 할 때
사용자가 터미널을 다른 작업에
사용해야할 때 (멀티태스킹)
생명 주기 로그아웃 후에도 작동 현재 세션에서만 작동


 

**윈도우 사용자를 위한 **

콘솔로 이동 명령 프롬프트(cmd)로 이동
`./gradlew` `gradlew.bat` 를 실행하면 됩니다.
명령 프롬프트에서 `gradlew.bat` 를 실행하려면 `gradlew` 하고 엔터를 치면 됩니다.
`gradlew build`
폴더 목록 확인`ls` `dir`
윈도우에서 Git bash 터미널 사용하기

 

 


 

 

 

  1. 브라우저 요청: IP 주소 질의
    • 사용자가 브라우저에 URL을 입력하거나 링크를 클릭합니다.
    • 브라우저는 해당 URL을 분석하고 DNS 서버에 도메인 이름의 IP 주소를 요청합니다.
  2. DNS 서버: IP 주소 응답
    • DNS 서버는 도메인 이름에 해당하는 IP 주소를 찾아 브라우저에 반환합니다.
    • 브라우저는 반환된 IP 주소를 사용해 요청을 보낼 서버를 식별합니다.
  3. 인터넷 경로 설정: TCP 연결 시도
    • 요청 데이터(HTTP 또는 HTTPS 요청)가 인터넷을 통해 여러 네트워크 장치(라우터, 스위치 등)를 거쳐 웹 서버로 전달됩니다.
    • 이 과정은 TCP/IP 프로토콜 스택을 통해 이루어집니다.
  4. 웹 서버 처리: HTTP 요청
    • 웹 서버는 클라이언트로부터 요청을 수신하고, 요청에 따라 정적 리소스(HTML, CSS, JS 파일) 또는 동적 콘텐츠(데이터베이스 조회, API 응답)를 생성합니다.
    • 필요한 경우 데이터베이스 서버나 다른 백엔드 서비스와 통신하여 데이터를 처리합니다.
  5. 응답 전송: HTTP 응답
    • 웹 서버는 요청 결과를 HTTP 응답으로 작성하여 브라우저로 반환합니다.
    • 이 응답에는 HTML 문서, CSS 스타일, JavaScript 코드 및 기타 리소스가 포함됩니다.
  6. 브라우저 렌더링:
    • 브라우저는 받은 HTML, CSS, JavaScript를 처리하여 웹 애플리케이션의 화면을 렌더링합니다.
    • 추가적인 요청(AJAX 또는 API 호출)을 통해 동적인 데이터가 업데이트될 수도 있습니다.
  7. 사용자 상호작용: 완료 후 TCP 연결 종료
    • 사용자는 웹 애플리케이션 화면에서 버튼 클릭, 입력, 탐색 등의 상호작용을 수행하며 추가 요청이 반복됩니다.

이 과정을 통해 사용자와 웹 애플리케이션이 실시간으로 데이터를 주고받고 상호작용합니다.

 

도메인 설정

웹 사이트의 도메인 네임을 설정하면 사용자가 웹 사이트를 더 쉽게 기억하고, 찾을 수 있기 때문에!

도메인이 웹 서버의 IP 주소를 가리키도록 DNS 서버 설정 업데이트

 

 


 

서버 환경 구축

어떤 서버를 사용하느냐

클라우드 vs On-premises

 

어떤 파일을 업로드 하느냐

1. 소스 코드로 전달

서버에서 빌드, 서버에 jdk 설치

 

2. jar 파일로 전달

로컬에서 빌드, 서버에 jre 설치

 

3. war 파일로 전달

로컬에서 빌드, 서버에 jre, WAS 설치

 

배포 파일 업로드 방식

리눅스 파일 전송법

FTP

LFTP

SFTP

WGET

GIT

SCP

RSYNC

DOCKER

 

 

웹 서버의 내부 구조

 

내부망에서는 접속이 가능한데 외부망에서 접속이 안되는 경우

 

공유기

외부에서 특정 포트로 접속하려면, 먼저 공유기의 방화벽에서 해당 포트로 들어오는 IP 주소를 허용하는 설정을 해야 합니다. 그런 다음, 공유기는 어떤 장비로 연결해야 할지 알지 못하므로 포트 포워딩 설정이 필요합니다. 포트 포워딩을 통해 외부에서 들어오는 특정 포트를 내부 서버의 대응 포트와 연결하는 규칙을 설정하여, 외부 IP에서 요청이 들어왔을 때 해당 서버로 트래픽을 전달할 수 있게 됩니다.

천장 함수(Ceiling Function)란?
천장 함수(Ceiling function)는 주어진 실수를 가장 작은 정수로 올림하는 함수입니다. 천장 함수는 일반적으로 **⌈x⌉**와 같은 형태로 표현됩니다.
천장 함수 (Ceiling Function): ⌈x⌉
x보다 크거나 같은 가장 작은 정수를 반환합니다.


올림 처리란?
올림 처리는 실수의 소수점 부분을 올려서 가장 작은 정수로 만드는 연산입니다. 예를 들어, 2.3을 올림 처리하면 3이 됩니다.
올림 처리 (ceil 처리): ⌈x⌉
예: ⌈3.2⌉ = 4, ⌈5.1⌉ = 6, ⌈−2.8⌉ = −2
음수일 경우에도 소수점을 버리지 않고 "가장 가까운 큰 정수"로 이동합니다.


천장 함수의 수식으로 표현
천장 함수는 x라는 실수를 가장 작은 정수로 올리는 함수입니다. 이 함수는 소수점 이하 부분을 올려서 정수로 만들기 위한 함수로 사용됩니다.
⌈x⌉: x보다 크거나 같은 가장 작은 정수
예: ⌈5.1⌉ = 6, ⌈2.8⌉ = 3


수식으로 표현된 올림 처리
올림 처리는 배열의 길이를 그룹 크기로 나누었을 때, 필요한 그룹 수를 계산하는 데 유용합니다. 예를 들어, 배열을 5명씩 그룹으로 나누고 싶을 때, 배열의 길이를 5로 나누고 나머지가 있는 경우 그룹을 하나 더 추가하는 방식입니다.

기본 수식 (천장 함수 사용):
배열의 길이 L과 그룹 크기 n이 주어졌을 때, 필요한 그룹 수는 올림 함수를 사용하여 계산할 수 있습니다:
⌈L / n⌉


천장 함수의 수식 변환 (수학적 근사)
천장 함수를 프로그래밍에서 바로 사용할 수 없는 경우, 수학적으로 올림 처리를 근사할 수 있는 수식을 사용할 수 있습니다. 바로 몫을 구하고, 그 값에 1을 더하는 방식입니다.

수식 근사:
배열 길이 L과 그룹 크기 n에 대해, 천장 함수를 사용하여 올림 처리된 그룹 수를 계산하는 수식은 다음과 같습니다:
⌈L / n⌉ = (L - 1) / n + 1

이 수식은 나누기 연산 후 소수점 부분을 버리고, 그 값에 1을 더하는 방식으로 천장 함수를 근사하여 올림 처리를 하는 효과를 얻습니다.

예시:
배열 길이 L = 12, 그룹 크기 n = 5일 경우:
(12 - 1) / 5 + 1 = 11 / 5 + 1 = 2 + 1 = 3

따라서, 12명을 5명씩 묶으면 3개의 그룹이 필요합니다.

Math.pow(2, 2);  // 4

Math.sqrt(4);  // 2

Math.abs(a - b);

'Java' 카테고리의 다른 글

웹 개발 기초 - 정적 컨텐츠, MVC와 템플릿 엔진, API  (1) 2024.12.22
Array 관련 내장함수  (1) 2024.11.10
String 관련 내장함수  (0) 2024.11.08
디자인 패턴(Design Pattern)  (0) 2024.11.05
Java introduction  (7) 2024.11.04

 

x = x.replaceAll("\\s", "");

x = x.replaceAll("\\s+", " ");

's' 한 번에 하나의 공백 매치를 대체하지만 's+'는 두 번째 매개변수로 전체 공백 시퀀스를 한 번에 대체합니다.
예를 들어 다음과 같은 경우:
String x = " text    with      WhiteSpace!  ";

-- ex_1)
x.replaceAll("\\s", "_");
x == "_text____with______WhiteSpace!__";

-- ex_2)
x.replaceAll("\\s+", "_");
x == "_text_with_WhiteSpace!_";

-- ex_3)
x.trim().split("\\s+");
x == ["text", "with", "WhiteSpace!"]

-- ex_4)
x.trim().split("[ ]+");
x == ["text", "with", "WhiteSpace!"]

 

두 예제의 차이점은 정규 표현식에서 사용하는 패턴에 있습니다.

  1. x.trim().split("\\s+"): \\s+는 모든 공백 문자(스페이스, 탭, 줄 바꿈 등)를 의미합니다.
  2. x.trim().split("[ ]+"): [ ]+는 한 개 이상의 공백 문자(스페이스)만을 의미합니다.

성능 차이

  • split("\\s+") 는 모든 종류의 공백 문자(스페이스, 탭, 줄 바꿈 등)를 처리하기 때문에, 정규식 엔진이 더 많은 작업을 수행하게 됩니다.
  • split("[ ]+") 는 공백(스페이스) 하나만을 처리하므로 더 간단한 정규식이며, 일반적으로 성능이 더 빠릅니다.

결론

  • x.trim().split("[ ]+") 이 일반적으로 더 빠를 것입니다.
  • 단, 텍스트에 스페이스 이외의 공백 문자가 포함될 가능성이 있거나 모든 공백 문자를 고려해야 한다면 split("\\s+")를 사용하는 것이 적절합니다.

Arrays 클래스: import java.util.Arrays;

 

1. Arrays.sort(array);

2. Arrays.copyOf(array, array.length + 1);

3. Arrays.copyOfRange(array, 0, array.length);

'Java' 카테고리의 다른 글

웹 개발 기초 - 정적 컨텐츠, MVC와 템플릿 엔진, API  (1) 2024.12.22
Math 관련 내장함수  (0) 2024.11.13
String 관련 내장함수  (0) 2024.11.08
디자인 패턴(Design Pattern)  (0) 2024.11.05
Java introduction  (7) 2024.11.04

지속적인 업데이트...

String 클래스: import java.lang.String;

lib 디렉토리 내부 jar 파일 안에 Java에서 사용하는 클래스들이 압축되어 있습니다.

java.lang은 java에서 자동으로 기술되기 때문에 선언하지 않아도 사용할 수 있습니다.

1. String.valueOf() 와 toString()의 차이점

두 메소드 모두 Object의 값을 String으로 변환하지만 변경하고자 하는Object가 null인 경우 다르다.
toString()과 같은 경우 Null PointerException(NPE)을 발생시키지만 
valueOf는 "null"이라는 문자열로 처리하고, 숫자의 경우 문자열로 형변환한다.

 

String.repeat(n);

String.replace(str, "");

String.replaceAll("[str]", ""); - "[str]" 정규식 표현

String.contains();

String.toCharArray();

String.charAt(n);

String.toLowerCase();

String.toUpperCase();

String.split(" ");

String.substring(0, n);

String.equals();

String.equalsIgnoreCase();

String.compareTo();

String.compareToIgnoreCase();

String.join("", arr);

String.startsWith(String prefix);

String.endsWith(String suffix);

String.indexOf(String);

-- 숫자를 문자열로 변환
class Solution {
    public String solution(int age) {
        String answer = "";
        for(char c : String.valueOf(age).toCharArray()) {
            answer += (char)('a' + (c - '0'));
        }
        return answer;
    }
}

'Java' 카테고리의 다른 글

웹 개발 기초 - 정적 컨텐츠, MVC와 템플릿 엔진, API  (1) 2024.12.22
Math 관련 내장함수  (0) 2024.11.13
Array 관련 내장함수  (1) 2024.11.10
디자인 패턴(Design Pattern)  (0) 2024.11.05
Java introduction  (7) 2024.11.04

+ Recent posts