🦁멋쟁이사자처럼 백엔드 부트캠프 13기 🦁
TIL 회고 - [21]일차
🚀21일차에는 디자인패턴의 Facade 퍼사드 패턴과 Stategy 전략 패턴을 실습해본 후 프론트엔드를 배울 수 있었다.
프론트엔드를 개인적으로 강의 듣거나 토이프로젝트를 진행할때 리액트, Expo 등으로 많이 접해봤다고 생각했다.
하지만 잘 알지 못했던 자바스크립트를 실행을 위한 Node, Node의 버전관리를 도와주는 nvm 등을 배워보니 기초적인 부분이 부족하다고 느꼈다.
회고를 통해 Node, nvm, npm 등을 다시 공부해보고 디자인패턴의 퍼사드, 전략 패턴 또한 정리해야겠다고 느꼈다.🚀
EJB
- Enterprise java Bean : 기업환경 시스템 구현을 위한 서버 측 컴포넌트 모델로 업무로직을 가진 서버 어플리케이션
즉 기업 애플리케이션을 위한 Java 구성 요소 프레임워크 - 스프링의 근간이 되는 기술로 분산처리에 강력한 기술
- 성능이 좋은 서버 한대로 동작하지 않고 적당한 서버로 여러 개를 동작시키는 것 ➡️분산처리
➡️EJB는 정해진 약속안에서 분산처리 기능을 도와줌 - 간단하고 유연한 POJO 스타일을 EJB에 도입하여 POJO를 기반으로 개선
- EJB 클래스에서 POJO : EJB는 단순한 POJO로 작성되고
필요한 기능은 어노테이션(@Entity, @Stateless 등)을 사용해 추가 - ➡️EJB + POJO : Java EE의 복잡성을 줄이고, 개발 효율성을 크게 향상
import javax.ejb.Stateless;
@Stateless
public class MyServiceBean {
public String sayHello(String name) {
return "Hello, " + name + "!";
}
}
- POJO로 작성된 MyServiceBean 클래스
- @Stateless 어노테이션 :
EJB 컨테이너가 이를 Stateless Session Bean으로 처리
Facade 퍼사드 패턴
- 구조적 패턴
- 내부 복잡한 서브 시스템을 “단순한 인터페이스”로 감싸서 제공 (포장지처럼 보이게 함 (=내부 시스템은 감춤))
클라이언트는 단일 메소드만 호출하면 된다
➡️ex. 자동차 시동 = 엔진 시스템을 몰라도 시동 버튼만 눌러도됨
➡️ex. 아이폰의 단축키 기능 등 - Wrapper패턴이라고도 함 ➡️복잡한 서브시스템을 “랩핑”으로 간단화
- 서브시스템과 클라이언트 간 결합도를 낮출 수 있다.
➡️서브 시스템 로직이 자주 바뀌어도 퍼사드 메소드는 그대로두고 내부만 변경
🚀실습 - 퍼사드 패턴 적용 전 (홈시어터 시스템)
// 홈시어터
class GigaGenie{
// ... 기능들
}
class JBLGo{
// ... 기능들
}
public static void main(String[] args) {
// 집의 기기들을 사용
// 1. 휴식 버튼 ON했을때 기능 - 음악감상하면서 웹서핑하기
// 1-1) 먼저 객체를 생성한다.
GigaGenie genie = new GigaGenie();
JBLGo jbl = new JBLGo();
genie.connBluetooth();
jbl.playMusic();
genie.setChannel("67");
genie.openWeb("유튜브");
jbl.volumnUp();
// 2. 잠잘때 기능 - 볼륨을 내리고, 블루투스 연결 해제 등
}
- 휴식하고자 버튼을 눌렀을때 내부적으로 저러한 기능들이 작동됨을 알 수 있다.
- 하지만 매번 저렇게 객체를 생성하고 메소드를 호출하는 것이 번거로울 수 있다.
- 이때 Facade패턴은 여러 메소드를 하나의 메소드로 묶어서 제공한다.
🚀실습 - 퍼사드 패턴 적용 후 (홈시어터 시스템)
class HomeTheaterFacade{
private GigaGenie genie;
private JBLGo jbl;
// 생성자부터 받아내도록 함
public HomeTheaterFacade(GigaGenie genie, JBLGo jbl) {
this.genie = genie;
this.jbl = jbl;
}
// 1. 휴식 취하기
public void getSomeRest(int time, BufferedReader br){
// ... 기능들
}
public void sleep(int time){
// ... 기능들
}
}
public static void main(String[] args) {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
GigaGenie genie = new GigaGenie();
JBLGo jbl = new JBLGo();
HomeTheaterFacade homeTheater = new HomeTheaterFacade(genie, jbl);
homeTheater.getSomeRest(18, br); // 1. 휴식 버튼 ON
homeTheater.sleep(23); // 2. 잠잘때 기능
}
🚀 실습 - Facade를 이용해 데이터 파싱하기
class FileReaderSubsystem{
public String readFile(String path) throws IOException {
String fileText = "";
FileReader reader = new FileReader(path);
int ch;
while ((ch = reader.read()) != -1) {
fileText += (char) ch;
}
return fileText;
}
}
class DataParserSubsystem{
public String parseData(String rawData){
String parsedData = "";
for(int i = 0; i < rawData.length(); i++){
if(!(rawData.charAt(i) == '@')) {
if(rawData.charAt(i) == '전'){
parsedData += '후';
continue;
}
parsedData += rawData.charAt(i);
}
}
return parsedData; // 파싱 결과 객체
}
}
class DataProcessorSubsystem{
public void processData(String data){
System.out.println("데이터 처리 로직 실행");
}
}
- 복잡한 서브시스템의 메소드를 정의
class DataFacade{
private FileReaderSubsystem fileReader = new FileReaderSubsystem();
private DataParserSubsystem parser = new DataParserSubsystem();
private DataProcessorSubsystem processor = new DataProcessorSubsystem();
public void handleDataFromFile(String path){
String raw = "";
String parsed = "";
try{
raw = fileReader.readFile(path);
parsed = parser.parseData(raw);
processor.processData(parsed);
}catch(Exception e){
e.printStackTrace();
}
// .. 결과출력
}
}
public class FacadeParser {
public static void main(String[] args) {
DataFacade facade = new DataFacade();
facade.handleDataFromFile("src/sample/FacadeTest.txt");
}
}
- Facade클래스에서 하나의 메소드 (handleDataFromFile)을 실행하여 서브시스템들이 동작하도록 함
- main에서는 파싱할 데이터의 경로를 넣어줌
Strategy 전략 패턴
- 행위 패턴
- 어떤 일의 방법을 유연하게 바꾸거나 확장하도록 돕는 패턴
- 동일한 목적의 작업들을 “다양한 전략”으로 수행할 수 있도록 설계
- 필요시 원하는 전략을 끼워넣어 사용 ➡️ex. 프린트 : 흑백/컬러/양면
- 만약 정렬 알고리즘을 구현한다면 if-else, switch보다는 각 정렬 알고리즘을 별도 전략 클래스로 분리 후
메인 로직에서 정렬 전략 인터페이스를 통해 실행 중 원하는 전략을 “동적으로” “주입해서 사용”하면 된다. - 알고리즘의 변경이 잦을때, 코드 수정 범위를 최소화할때 필요
▶️실습 - 일반적 Stategy 패턴 사용의 경우
interface Strategy{
void execute();
}
class ConcreteStrategyA implements Strategy{// ...오버라이딩}
class ConcreteStrategyB implements Strategy{// ...오버라이딩}
class ConcreteStrategyC implements Strategy{// ...오버라이딩}
class Context{
private Strategy strategy;
public Context(Strategy strategy) {
this.strategy = strategy;
}
public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
public void performAction(){
strategy.execute();
}
}
- 실행 인터페이스를 통해 구현하고
Context 클래스(=메인로직)에서 전략을 바꿔 execute()를 수행할 수 있도록 함 (=performAction())
// 전략 A 사용
Context context = new Context(new ConcreteStrategyA());
context.performAction();
// 전략 B 사용 (A->B 교체)
context.setStrategy(new ConcreteStrategyB());
context.performAction();
// 전략 C 사용 (B->C 교체)
context.setStrategy(new ConcreteStrategyC());
context.performAction();
🚀실습 - 옷장 시스템 (Strategy)
- 상의, 하의만 가지던 전략을 “신발”을 추가하여 갈아입기 시스템을 구현
interface ClothStrategy{
void wearing(String beforeCloth, String afterCloth);
}
class ConcreteTop implements ClothStrategy{ //...오버라이딩 }
class ConcreteBottom implements ClothStrategy{ //...오버라이딩 }
class ConcreteShoes implements ClothStrategy{ //...오버라이딩 }
class ClothContext{
private ClothStrategy clothStrategy;
private String beforeCloth;
private String afterCloth;
// 생성자
public ClothContext(ClothStrategy clothStrategy) {
this.clothStrategy = clothStrategy;
}
// ... 옷교체 Setter
// 전략 교체 Setter
public void setClothStrategy(ClothStrategy clothStrategy) {
this.clothStrategy = clothStrategy;
}
public void changeCloth(){
clothStrategy.wearing(beforeCloth, afterCloth);
}
}
ClothContext context = new ClothContext(new ConcreteTop());
context.setBeforeCloth("맨투맨");
context.setAfterCloth("니트");
context.changeCloth();
- 이처럼 beforeCloth와 afterCloth를 설정하여 갈아입는 시스템을 구현
context.setClothStrategy(new ConcreteShoes());
context.setBeforeCloth("슬리퍼");
context.setAfterCloth("스니커즈");
context.changeCloth();
- 전략 추가 (+신발 갈아신기)
프론트엔드 Frontend
- HTML (HyperText Markup Language) : 정적인 언어로 매번 똑같은 내용, 화면이 나올 수 있음
- HTML은 XML(=확장가능한 마크업 언어)를 규칙을 따르는 형태
- 문서와 문서를 연결하는 Hyper Link (하이퍼링크) 개념이 도입
- 자바스크립트 (Javascript) : 넷스케이프 사의 동적인 언어로 다양한 콘텐츠 표현이 가능
▶️실습 - vsCode로 HTML 만들기
- vsCode에서 원하는 디렉토리 열기 폴더에서 cmd를 열고 ➡️code .
- vsCode에서 HTML 폼 바로 만들기 ➡️ ! + Enter
설정 :
- extension → prettier code format 설치 (좀 더 편한 코드 포맷팅을 도와줌)
→ 왼쪽 밑 Settings → formatting → Editor Paste, save 체크 (저장, 붙여넣을때 자동으로 formatting을 맞춰줌)
- settings → defualt formatter 검색 후 → prettier로 변경
▶️실습 - nvm & node 설치
- Node : “크롬 V8 자바스크립트 엔진으로 빌드된 자바스크립트 런타임”
- 설치 후 확인 ➡️nvm -v
- node.js 설치
- 설치된 node.js 확인 ➡️nvm ls
- 자바를 실행시키기 위해서는 JDK가 필요
자바스크립트를 실행하기 위해서는 Node가 필요
- 브라우저의 F12 ➡️개발자 도구의 Console을 통해서도 자바스크립트 문법을 수행 가능
<body>
<h1>-- Frontend Start-- !</h1>
<p>Tag 'p' Tester</p>
<h2>Tag 'h2' Tester</h2>
<h3>Tag 'h3' Tester</h3>
<!-- Javascript console.log Tester -->
<script>
console.log("HTML Tag 'script' Tester");
</script>
</body>
- HTML에서 body태그 안에 script 태그를 만들고 console.log()를 실행 가능
- 자바스크립트 실행할때 브라우저에서는 node가 반드시 필요하진 않다.
➡️브라우저 내에 자바스크립트를 해석해서 실행하는 도구를 이미 가지고 있기 때문 - 브라우저 밖에서도 자바스크립트를 실행하고 싶을때 도와주는 것 ➡️node
nvm
- node는 버전별로 조금은 다른 기능을 가진다. ➡️자바스크립트의 변화가 많았기때문이다.
- JDK 버전 변경 시 (이전버전 → 21버전) ‘이전 버전 삭제’ , ‘새 버전 다운로드’ , ‘환경 변수 변경’ 등을 수행해야했음
자바스크립트에서 이러한 과정을 쉽게 관리할 수 있도록 도와주는 도구
➡️nvm (Node Version Manager, 노드버전관리자) : JDK 버전 관리를 도와줌
npm
- Node Package Manager
- Node.js로 개발된 프로그램(npm 패키지)를 편리하게 설치, 업데이트 및 삭제 해 주는 프로그램
- 설치 후 npm 명령어를 통해 Node.js로 작성된 패키지 관리
- Node.js 설치 시, npm이 같이 설치
- 자바에서 Maven, Gradle이 라이브러리, 패키지를 관리해주는 역할
자바스크립트에서는 npm이 그 역할
➡️npm 프로젝트를 생성하면 필요한 라이브러리, 패키지들을 프로젝트 자체에서 다운받아 사용할 수 있게 도와줌
▶️실습 - nvm 설치
- nvm 버전확인
- 설치된 node.js 확인
- LTS버전을 권장 >> [LTS 최신 기준 설치 방법] ➡️nvm install 22.12.0 + Enter
- nvm을 사용하지 않으면 직접 사이트에서 버전 비교 후 다운로드 해야함
➡️nvm을 통해 버전관리를 자동으로 관리가능
- nvm list (혹은 nvm ls) : nvm 설치 완료 후 list 확인 ➡️출력 : 22.12.0
- ➡️nvm use 22.12.0 : 반드시 버전 사용을 명시해야한다.
- 버전 사용 명시 후 리스트 확인 시 ”* 22.12.0 (Currently using 64-bit executable)” 출력되면 완료
- 💡버전 삭제 : ➡️nvm uninstall [version]
▶️실습 - npm 설치 & node 프로젝트 만들기
- node를 이용해서 서버를 동작하고자 할때 간단하게 웹서버를 띄워야하는데
웹 서버에 필요한 라이브러리를 설치해서 사용 - node 프로젝트 만들기
➡️mkdir [프로젝트를 만들 디렉토리 생성]
➡️cd [생성한 디렉토리]
➡️npm init + Enter : 질문은 모두 무시 후 Enter만 입력 : 프로젝트의 구조를 생성해줌 - package.json : init을 통해 만들어지며 프로젝트가 어느 정보를 가져야할지 정보를 주는 역할
package.json이 있어야 npm 프로젝트 ➡️자바 gradle프로젝트에 build.gradle 이 있는 것과 마찬가지
▶️실습 - lite-server (서버) 설치
- 서버 설치 ➡️npm install lite-server --save-dev
- --save-dev 옵션 : lite-server라는 곳에 의존성을 추가, package.json에 “devDependencies” 부분에 자동으로 추가됨
❓Dependencies가 아닌 devDependencies로 명시된 이유
➡️-dev 옵션을 통해 "개발 시에 사용하는 의존성(라이브러리)임을 명시"
- 명령 추가 ➡️package.json의 scripts 부분에 추가
"start" : "npm run lite",
"lite" : "lite-server",
- 서버 실행 ➡️npm start
▶️실습 - 페이지 만든 후 서버로 페이지에 접속
InitPage.html 작성
- ➡️npm start : 서버 접속 정보가 표시
- ➡️접속방법 : localhost:3000/InitPage.html
- 클라이언트가 포트번호를 명시하여 서버에 요청 ➡️서버는 해당 포트에서 동작하고있는 내용을 브라우저에 표시
- InitPage.html 브라우저 출력 결과
- ⚠️간혹 서버에 따라 포트번호를 바꾸며 요청에 대한 응답을 처리하기도하지만
자바스크립트의 lite-server는 일반적으로 포트번호 3000번으로 동작 - ⚠️만약 다른 프롬프트에서 npm start를 통해 “또 하나의 서버를 열면”
포트번호는 3001번 처럼 다른 포트번호를 할당하여 동작 - 포트번호 직접 지정 : [bs-config.json]을 만들고 ➡️{ “port” : 4000 } 작성
- 프론트엔드에서는 대체로 3000번 포트 사용
💡자바의 톰캣에서는 대체로 8080번 포트 사용
💡MySQL에서는 대체로 3306번 포트 사용
index.html 작성
- ➡️접속방법 : localhost:3000
- 만약 페이지가 수정된다면 ReloadingBrowsers 문구가 출력 ➡️“핫 리로드 (Hot reload)”
- 서버 종료 : ➡️Ctrl + C → Y 입력
- vscode 편집기에서 내장 터미널 사용 : ➡️Ctrl + Shift + ` (역슬래시) : npm start로 서버 구동 가능
💡프론트엔드의 기초를 배우면서 자바스크립트에서 서버를 구동시키는 방법을 처음 접할 수 있었고
조금 더 배워서 프론트엔드로 게시판의 UI를 구현하고 백엔드 MySQL 데이터베이스로 회원관리나 게시판 글 관리 등을
구현할 수 있을 거란 생각도 들었다.
이번 회고에서 기존에는 자바스크립트의 기초 문법만 조금 알고 있었는데 자바스크립트의 npm, nvm 등을 통해 라이브러리를 추가해줄 수 있다는 것이 가장 기억에 남았다. 🚀
'Recording > 멋쟁이사자처럼 BE 13기' 카테고리의 다른 글
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_23일차_"CSS 선택자와 위치 속성" (0) | 2025.01.03 |
---|---|
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_22일차_"HTML과 CSS" (3) | 2025.01.02 |
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_20일차_''디자인패턴" (2) | 2024.12.30 |
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_19일차_''객체지향원칙 OOP" (3) | 2024.12.27 |
[멋쟁이사자처럼 부트캠프 TIL 회고] BE 13기_18일차_''스레드 Thread" (0) | 2024.12.26 |