4강 레퍼클래스 로또 번호 생성기 질문 있습니다. package class04wrapperClass; import java.util.Random; public class Lottery { public static void main(String args[]) { //랜덤 생성자 선언 ==> 로또 값이 그때 그때 바뀜 Random random = new Random(); //로또 범위 지정 배열 int[] randomArray = new int[6]; //로또 배열에 로또 값 넣기 for (int i = 0; i < randomArray.length; i++) { int randomValue=random.nextInt(45)+1; randomArray[i]=randomValue; if (randomArray[i]==randomArray[i++]||randomArray[i]==0) randomArray[i]=random.nextInt(45)+1; } for(int i =0; i<randomArray.length; i++){ System.out.print(randomArray[i]+" , "); } } } 이렇게 풀었는데 이것도 올바른 풀이 일까요???
import React, { useState, MouseEvent } from "react"; import * as S from "./mypoint.index.styles"; import TapPointLoading from "./mypoint_loading"; import TapPointBuying from "./mypoint_buying"; import TapPointAll from "./mypoint_all"; import TapPointSelling from "./mypoint_selling"; export default function MyPoint(): JSX.Element { const [selectedValue, setSelectedValue] = useState<{ name: string; index: number; }>({ name: "전체내역", index: 0, }); const MyPageHeadInfoButton = [ { name: "전체내역", component: <TapPointAll /> }, { name: "충전내역", component: <TapPointLoading /> }, { name: "구매내역", component: <TapPointBuying /> }, { name: "판매내역", component: <TapPointSelling /> }, ]; const onClickTap = ( event: MouseEvent<HTMLDivElement>, index: number ): void => { const newValue = event.currentTarget.id; setSelectedValue({ name: newValue, index, }); }; // 버튼 클릭으로 해당 data 값을 보여주기 위함 const renderData = (): JSX.Element | undefined => { return ( <S.TableWrap> {/* 해당 탭의 배열의 객체 name통해 컴포넌트 가져옴 */} {MyPageHeadInfoButton.map((el) => { if (el.name === selectedValue.name && el.component) { return <div key={el.name}>{el.component}</div>; } return null; })} </S.TableWrap> ); }; return ( <S.Wrap> <S.MyPageHeadWrap> <S.MyPageHeadBtn> {/* 서브 탭 버튼 */} {MyPageHeadInfoButton.map((el, index) => ( <S.MyPageInfoBtn key={el.name} id={el.name} onClick={(event) => onClickTap(event, index)} selected={selectedValue.name === el.name} > {el.name} </S.MyPageInfoBtn> ))} </S.MyPageHeadBtn> </S.MyPageHeadWrap> <S.MyPageBodyWrap> {/* 해당 탭 data */} <div>{renderData()}</div> </S.MyPageBodyWrap> </S.Wrap> ); } 이렇게 탭을 클릭을 해서 해당 컴포넌트가 보이도록 했습니다. 그러면서 각각의 API data도 받아와 cache에 저장을 하도록 해 추가 API 요청이 일어나지 않도록 했는데 여기서 로그아웃을 하고 다른 아이디로 로그인을 하면 이전의 로그인 했던 data가 그대로 남아있어 최신 data를 가져오기 위해 여러가지 방법으로 시도했습니다. 로그아웃 시 useApolloClient를 활용해 cache를 삭제 했습니다. 이렇게 하면 다시 로그인 한 유저의 data를 잘 가져오는데 로그아웃을 하면서 cache data가 삭제되니 다른 API, Board, Markets 등 해당 page의 사용한 query문의 data를 다시 요청하는 문제가 있습니다. refetch()로 query문을 선언하면 해당 refetch()를 실행하지 않아도 API 요청이 일어나 refetchQueries를 사용해 data 최신화 하려는데 그렇게 되면 모든 탭을 refetch 해줘야 되는 문제가 있습니다. 각 탭 이동마다 API 요청 나가는게 싫어서 fetchporicy나 refetch()를 사용 하지 않았는데 보통 어떻게 사용을 하나요? 로그인에 의한 data는 탭 이동마다 refetch를 시켜주는게 좋을까요? 그리고 구매, 충전 등 하면 바로 MyPoint에 업데이트 되도록 client.writeQuery / readQeury 나 refetchQueries를 사용했는데 이런 결제 정보 같은거는 refetch로 실시간으로 data를 가져오는게 좋겠죠? 로그인, 로그아웃은 LayoutHeader에서 사용하고 있습니다.
안녕하세요. 이전 7강의 메모리 구조와 헷갈리는 부분이 있어서 질문드립니다. 7강의 자바 메모리 구조에서는 다음과 같이 메서드는 공통됐기 때문에 메서드 영역에서 관리한다고 이해했습니다. 그러나 상속 부분에서는 힙영역에서 메서드를 관리하고 사용하는 것처럼 되어있어서 헷갈립니다. 설명을 편리하게 하고자 이렇게 설명하신 걸까요?? 잘못 이해한 부분이 어딘지 모르겠습니다 ㅠㅠ 감사합니다.
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] jpql 구문이 실행될 때 flush가 자동으로 호출 된다고 하셨는데 당연히 flush로 쓰기 지연 SQL 저장소에 있는 쿼리들을 데이터베이스에 반영하고 commit 한 후 jpql 구문이 실행되는거겠죠?
테스트 코드는 오류 없이 초록불이 뜨는데 DB 내 테이블 생성이 안 됩니다. 강사님의 다른 강의와, 응용 프로젝트를 만들어 볼 땐 잘 됐어서 자주 묻는 질문들을 참고해도 어느 곳이 문제인지 잘 모르겠네요ㅠㅠ.. 일단 올려두고 계속 방법을 찾아보겠습니다! package jpabook.jpashop; import org.assertj.core.api.Assertions; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.annotation.Rollback; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.transaction.annotation.Transactional; import static org.junit.Assert.*; @RunWith(SpringRunner.class) @SpringBootTest public class MemberRepositoryTest { @Autowired MemberRepository memberRepository; @Test @Transactional @Rollback(false) public void testMember() throws Exception{ //given Member member = new Member(); member.setUsername("memberA"); //when //ctrl+alt+v 변수 뽑기 Long saveId = memberRepository.save(member); Member findMember = memberRepository.find(saveId); //then Assertions.assertThat(findMember.getId()).isEqualTo(member.getId()); Assertions.assertThat(findMember.getUsername()).isEqualTo(member.getUsername()); Assertions.assertThat(findMember).isEqualTo(member); //JPA 엔티티 동일성 보장 } } spring: application: name: jpashop #port번호 설정 server: port: 8050 #DB datasource: url: jdbc:h2:tcp://localhost/~/jpashop username: sa password: driver-class-name: org.h2.Driver #JPA jpa: hibernate: ddl-auto: create properties: hibernate: show_sql: true format_sql: true logging: level: org.hibernate.SQL: debug org.hibernate.orm.jdbc.bind: trace
학습하는 분들께 도움이 되고, 더 좋은 답변을 드릴 수 있도록 질문전에 다음을 꼭 확인해주세요. 1. 강의 내용과 관련된 질문을 남겨주세요. 2. 인프런의 질문 게시판과 자주 하는 질문(링크)을 먼저 확인해주세요. (자주 하는 질문 링크: https://bit.ly/3fX6ygx) 3. 질문 잘하기 메뉴얼(링크)을 먼저 읽어주세요. (질문 잘하기 메뉴얼 링크: https://bit.ly/2UfeqCG) 질문 시에는 위 내용은 삭제하고 다음 내용을 남겨주세요. ========================================= [질문 템플릿] 1. 강의 내용과 관련된 질문인가요? (예/아니오) 2. 인프런의 질문 게시판과 자주 하는 질문에 없는 내용인가요? (예/아니오) 3. 질문 잘하기 메뉴얼을 읽어보셨나요? (예/아니오) [질문 내용] 여기에 질문 내용을 남겨주세요. gradlew build를 하면 계속 오류가 떠서 게시판 글들을 살펴보았는데요. V3 실시간 검사를 해제하면 된다는 이야기가 있길래 해보려고 했는데, 비밀번호가 걸려있어서 실시간 검사 해제가 안 됩니다..인터넷 검색을 해도 비밀번호를 찾는 방법은 안 나오네요. 이거 때문에 지금 이틀 동안 진도가 안 나가는데 어떻게 해야 할까요?
안녕하세요! CentOS의 EOS가 종료됨에 따라 레포지토리가 더이상 사용할 수 없게 되어서 docker build -t mysql57.0.0 ./ 명령어 시에 아래와 같은 에러가 발생합니다. $ docker build -t mysql57.0.0 ./ ... ... => ERROR [ 5/12] RUN yum install -y perl.x86_64 libaio.x86_64 numactl-libs.x86_64 net-tools.x86_64 sudo.x86_64 Could not retrieve mirrorlist http://mirrorlist.centos.org/?release=7&arch=x86_64&repo=os&infra=container error was 0.572 14: curl#6 - "Could not resolve host: mirrorlist.centos.org; Unknown error" 이는 레포지토리가 더이상 지원하지 않아서 yum install -y 할 때 나타나는 에러입니다. 그래서 /etc/yum.repos.d/CentOS-Base.repo 의 내용을 아래와 같이 변경해야합니다. [base] name=CentOS-$releasever - Base # original #mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os&infra=$infra #baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/ # new baseurl=http://centos.mirror.cdnetworks.com/7/os/x86_64 gpgcheck=1 enabled=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 #released updates [updates] name=CentOS-$releasever - Updates # original #mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates&infra=$infra #baseurl=http://mirror.centos.org/centos/$releasever/updates/$basearch/ # new baseurl=http://centos.mirror.cdnetworks.com/7/updates/x86_64 gpgcheck=1 enabled=1 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 #additional packages that may be useful [extras] name=CentOS-$releasever - Extras # original #mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras&infra=$infra #baseurl=http://mirror.centos.org/centos/$releasever/extras/$basearch/ # new baseurl=http://centos.mirror.cdnetworks.com/7/extras/x86_64 gpgcheck=0 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 #additional packages that extend functionality of existing packages [centosplus] name=CentOS-$releasever - Plus # original #mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplus&infra=$infra #baseurl=http://mirror.centos.org/centos/$releasever/centosplus/$basearch/ # new baseurl=http://centos.mirror.cdnetworks.com/7/centosplus/x86_64 gpgcheck=1 enabled=0 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 그리고 CentOS-Base.repo 파일을 Dockerfile에 추가하였습니다 FROM centos:7 COPY ["Percona-Server-client-57-5.7.30-33.1.el7.x86_64.rpm",\ "Percona-Server-server-57-5.7.30-33.1.el7.x86_64.rpm", \ "Percona-Server-shared-57-5.7.30-33.1.el7.x86_64.rpm", \ "Percona-Server-shared-compat-57-5.7.30-33.1.el7.x86_64.rpm", \ "node_exporter-1.0.1.linux-amd64.tar.gz", \ "mysqld_exporter-0.12.1.linux-amd64.tar.gz", \ "start_node_exporter.sh", \ "start_mysqld_exporter.sh", \ ".my.cnf","/tmp/"] COPY CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo USER root RUN groupadd -g 1001 mysql RUN useradd -u 1001 -r -g 1001 mysql RUN yum install -y perl.x86_64 \ libaio.x86_64 \ numactl-libs.x86_64 \ net-tools.x86_64 \ sudo.x86_64 RUN yum downgrade -y openssl-libs-1.0.2k-16.el7 -> 다운그레이드! ... ... ... COPY CentOS-Base.repo /etc/you.repos.d/CentOS-Base.repo를 추가하고 나서 docker build -t mysql57.0.0 ./ 실행하니까 정상적으로 잘 되네요! 그리고 이유는 모르겠으나 yum install -y penssl-libs-1.0.2k-16.el7을 하면 패키지 버전 충돌때문에 빌드 시 에러가 발생합니다. yum install -y penssl-libs-1.0.2k-16.el7를 제거하고 yum downgrade -y openssl-libs-1.0.2k-16.el7를 추가하니까 빌드가 잘됩니다.. 이유는 레포지토리가 변경되면서 뭔가.. 그런거 같기도하고 잘모르겠네요 감사합니다.!
그런데 글만 회고록에 글만입력하면 오류가 납니다. 오류의 원인은 speed.js파일 때문이라고 합니다. 현재 코드는 아래와 같습니다. 허파가 뒤집어집니다. import { Input, Button} from 'antd'; const { TextArea } = Input; import { useState } from "react";// 저장하는 곳임포트 const DiaryInput = ({ isLoading, onSubmit }) => { const [userInput, setUserInput] = useState(""); // isLoading 로딩상태에서 사용하는 변수 // inSubmit 다입력 작성하면 사용 const handleUserInput = (e) => { setUserInput(e.target.value); }; const handleClick = () => { onSubmit(userInput); }; return ( <div> <TextArea value={userInput} onChange={handleUserInput} placeholder="오늘 일어난 일들을 간단히 적어주세요." /> <Button loading={isLoading} onClick={handleClick}> GPT 회고록을 작성해줘! </Button> </div> ); } export default DiaryInput; // import { Input , Button} from 'antd'; // import { useState } from 'react'; // const { TextArea } = Input; // const DiaryInput = ({isLoading, onSubmit}) => { // const [userInput, setUserInput] = useState(""); // //사용자의 입력을 받아 상위 컴포넌트로 넘기기 // // 로딩상태에서는 제출버튼 못누루게 // const handleUserInput =(e)=>{ // setUserInput(e.target.value); // const handleClick = ()=>{ // onSubmit(userInput); // } // } // return ( // <div> // <TextArea value={userInput} onChange={handleUserInput} placeholder='오늘 하루 회고'/> // <Button loading={isLoading} onClick={handleClick}>GPT회고록 시작</Button> // </div> // ); // }; // export default DiaryInput; import { useState } from 'react'; import { CallGPT } from './api/gpt'; import DiaryInput from './components/DiaryInput'; const dummyData = { "title": "고립된 개발자의 고민", "thumbnail": "https://source.unsplash.com/1600x900/?programming", "summary": "혼자 코딩과제를 진행하면서 걱정이다.", "emotional_content": "최근 혼자 코딩과제를 진행하면서, 협업이 없이 모든 것을 혼자 결정하고 해결해야 한다는 부담감에 많이 무겁습니다. 강의를 듣고 최선을 다해 프로젝트를 진행했지만, 예상치 못한 버그들로 인해 스트레스가 많이 쌓였습니다. 스택오버플로와 GPT를 통해 문제를 해결하긴 했지만, 이러한 문제해결 방식이 정말로 제 개발 실력을 향상시키는지에 대해 의문이 듭니다. 왠지 스스로의 능력을 시험할 기회를 잃은 것 같아 아쉽고, 불안감도 커지고 있습니다.", "emotional_result": "이 일기에서 감지되는 감정은 불안, 부담감, 그리고 자신감의 결여입니다. 고립된 상황에서의 성공에 대한 압박감과 문제 해결 방법에 대한 의심은 정서적으로 큰 부담을 주고 있습니다. 자기 효능감이 낮아짐을 느끼는 상황입니다.", "analysis": "고립되어 문제를 해결하는 과정은 큰 스트레스와 불안을 유발할 수 있습니다. '혼자서 하는 일은 좋은 일이든 나쁜 일이든 더욱 크게 느껴진다'는 에릭 에릭슨의 말처럼, 혼자서 모든 것을 해결하려는 시도는 때로는 개인의 성장에 도움이 될 수 있지만, 지속적인 고립은 자기 효능감을 저하시킬 수 있습니다. 이러한 상황에서는 자신의 노력을 인정하고, 필요한 경우 도움을 요청하는 것이 중요합니다.", "action_list": [ "프로젝트 중 발생하는 문제를 혼자 해결하려 하지 말고, 멘토나 동료 개발자와 상의를 통해 해결 방안을 모색하라.", "정기적으로 자신의 학습 방법과 진행 상황을 평가하여, 필요한 경우 학습 방식을 조정하라.", "개발 과정에서의 스트레스 관리를 위해 적절한 휴식과 여가 활동을 통해 정서적 안정을 찾으라." ] }; function App() { const [data, setData] = useState(dummyData); // 우선 빈문자열로 해놓고 const [isLoading, setIsLoading] = useState(false); const handleClickAPICall = async (userInput) => { try { setIsLoading(true);// 처음에는 로딩을 트루 const message = await CallGPT({ prompt: `${userInput}`, }); // Assuming callGPT is a function that fetches data from GPT API setData(JSON.parse(message)); } catch (error) { // Handle error (you might want to set some error state here) } finally { setIsLoading(false);//다음에는 펄스로 } }; const handleSubmit = (userInput) => { handleClickAPICall(userInput); }; console.log(">>data", data); return ( <> <DiaryInput isLoading={isLoading} onSubmit ={handleSubmit} /> <button onClick={handleClickAPICall}>GPT API call</button> <div>title : {data?.title}</div> <div>analysis : {data?.analysis}</div> <div>emotional_content : {data?.emotional_content}</div> <div>emotional_result : {data?.emotional_result}</div> </> ); }; export default App; // import { useState } from "react"; // import { CallGPT } from "./api/gpt"; // import { message } from "antd"; // import DiaryInput from "./components/DiaryInput"; // const dumyData = JSON.parse(` // { // "title": "당황스러운 예제 에러", // "thumbnail": "https://source.unsplash.com/1600x900/?confused", // "summary": "가끔 예제 에러가 발생하여 당황함", // "emotional_content": "가끔 예제 에러가 나타나는 것이 정말 당황스럽다. 이런 상황들은 예상치 못한 문제로 인해 나를 혼란스럽게 만든다. 그럼에도 불구하고, 이런 에러들은 동시에 나의 문제 해결 능력을 시험한다.", // "emotional_result": "당황스러움과 혼란스러움이 느껴진다. 그러나 이는 예상치 못한 문제에 대처하는 능력을 향상시키는 과정일 수 있다.", // "analysis": "당신의 당황함과 혼란스러움은 예상치 못한 상황에 대한 불안감과 두려움을 반영할 수 있습니다. 하지만, '문제는 기회다'라는 유명한 격언을 기억하십시오. 이러한 에러들은 당신의 문제 해결 능력을 향상시키는 좋은 기회일 수 있습니다.", // "action_list": [ // "예상치 못한 에러에 대비하는 습관 만들기", // "문제 해결 능력 향상을 위한 자기계발", // "당황하지 않고 차분하게 상황을 평가하는 능력 기르기" // ] // } // `); // function App() { // const [data, setData] = useState(dumyData); // const [isLoading, setIsLoading] = useState(false); // // 여기로딩상태가 // const handleClickAPICall = async (userInput) => { // try{// try catch로 감싸서, 처음에는 로딩상태를 트루라고 하고 // setIsLoading(true); // const message = await CallGPT({ // prompt:'{userInput}', // }); // setData(JSON.parse(message));// 그리고 데이터가 잘오면 받아보자 // } catch (error){ // }finally{ // setIsLoading(false);// 나중에는 false라고 하자 // } // }; // const handleSubmit = (userInput)=>{ // handleClickAPICall(userInput); // }; // console.log(">>data", data); // return ( // <> // <DiaryInput isLoading={isLoading} onSubmit={handleSubmit} /> // // 여기로 옴 // <button onClick={handleClickAPICall}>GPT API call</button> // <div>data : {data?.title}</div> // <div>thumbnail: {data?.thumbnail}</div> // <div>summary : {data?.summary}</div> // <div>emotional_resul : {data?.emotional_resul}</div> // <div>emotional_content : {data?.emotional_content}</div> // <div>analysis: {data?.analysis}</div> // <div>action_list: {data?.action_list}</div> // </> // ); // } // export default App ;{ "name": "my-gpt-diary", "private": true, "version": "0.0.0", "type": "module", "scripts": { "dev": "vite", "build": "tsc -b && vite build", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "preview": "vite preview" }, "dependencies": { "@ant-design/icons": "^5.4.0", "antd": "^5.20.1", "react": "^18.3.1", "react-dom": "^18.3.1", "styled-components": "^6.1.12" }, "devDependencies": { "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@typescript-eslint/eslint-plugin": "^7.15.0", "@typescript-eslint/parser": "^7.15.0", "@vitejs/plugin-react": "^4.3.1", "eslint": "^8.57.0", "eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-react-refresh": "^0.4.7", "typescript": "^5.2.2", "vite": "^5.3.4" } }
MyLinkedListV3 stringList = new MyLinkedListV3<>(); 에서는 <> 가 있어야 하는데 왜 MyLinkedListV3 stringList = new MyLinkedListV3[CAPACITY]; 에서는 <> 를 쓰면 안되는지 궁금합니다.
2:30 를 보면 영한님께서 해시 테이블에서 Linkedlist 를 전체 버킷의 컨테이너로 사용하셨는데, ArrayList 를 전체 버킷의 컨테이너로 사용해도 전혀 문제가 없지 않나요 ? 따라서, 해시 테이블에서 ArrayList 를 전체 버킷의 컨테이너로 사용하고, 각 버킷 내에서는 LinkedList 를 사용해 충돌을 처리하는 방법도 괜찮지 않나요 ?
입문자를 위한 Spring Boot with Kotlin - 나만의 포트폴리오 사이트 만들기
여기서 experience를 모델에서 못찾아서?? experience.startYearMonth 등 인식이 안되는것 같습니다. cannot resolve라고 뜹니다. 혹시 제가 컨트롤러라든지 DTO라든지 잘못적고 놓쳤나보다 하고 봤는데 왜 안되는지 못찾겠습니다. 한번 확인 가능할까요? 컨트롤러 서비스 DTO 데이터 초기화 이렇게 타임리프 적용이 안될 떄는 어떻게 찾는게 좋은 방법일까요?
안녕 하세요. 궁금증이 생겨서 질문을 남깁니다. 공식 서포터즈님들의 댓글 들을 보다가, "이분 들은 강의를 완강하는데 얼마나 걸리까?"라는 생각을 하게 되었습니다. 뜬금없는 질문이긴 합니다만, 만약에 시간의 여유가 아주 넘쳐 난다면 , 공식 서포즈님들 이나, 정식 개발자 분들(개발자로 취직하신 분이시거나 프리랜서 등등)은, 영한님의 강의 중급1편, 중급 2편을 완강(체득 포함)하는데 시간이 얼마나 걸리나요? 답변 부탁 드립니다.
안녕하세요. 의존성 주입 연습하기 강의 중 10:30 쯤에서 test 하는 중 java.lang.IllegalStateException: Failed to load ApplicationContext 예외가 발생했습니다. 여러 가지 자료들을 검색해 보고 시도해봤으나 안 됩니다. 어떻게 하면 되는지요?
DevOps를 위한 Docker 가상화 기술 (Private Harbor Registry)
Prometheus 설명 부분에서요, 컨테이너 상태에 대한 Metrics 수집 부분에 대해서 질문있습니다. 실무에서 컨테이너 환경에서 애플리케이션을 개발한적은 없고, Prometheus, Grafana, Loki, Promtail 정도만 컨테이너 기반에서 로그 수집하는 정도로만 활용해봤는데요, 스프링 부트 환경에 액츄에이터, 마이크로미터 라이브러리 구성해서 N개의 서버(운영, 개발, 스테이징 서버 등)에서 프로파일에 따른 로그를 수집하고, Promtail도 각 서버에 설치하고, 별도의 모니터링 서버에 컨테이너 기반으로 Prometheus, Grafana, Loki 셋팅해서 사용하고 있습니다.(이렇게 구성한 아키텍쳐?가 베스트 프랙티스인지는 잘모르겠네요) 그런데 해당 강의를 듣고 생각한게 컨테이너 기반의 애플리케이션을 올릴 경우 추가적으로 컨테이너 상태에 대한 메트릭 수집이 있을 것 같은데요, 컨테이너 실행/중지 같은 상태 제외하면 어떤 유의미한 데이터를 수집할 수 있는지 감이 안오는데, 어떤것들이 있을까요? CPU나 메모리 같은 리소스 정도가 있을꺼 같고.. 추가적으로 컨테이너 환경의 애플리케이션을 구성한다면 MSA 환경이 아니더라도 로그 정보를 별도의 로그 서버에서 관리하는게 일반적인가요? 이 강의를 듣기전에는 애플리케이션 서버가 당연히 로그도 수집하는거로 생각해서 Promtail도 각 로그파일이 있는 서버에 다 설치했거든요. 이전 섹션에서 로그를 별도 컨테이너에서 관리하는거 보고 궁금증이 생겼습니다.