아....

얼마전에 h2 세팅만 해놓고 다시 h2 접속하려니까 오류가 난다...

 

개발은 항상 개발과정보다 세팅 과정이 은근 더 어려운거 같댜ㅑ.......

 

1. 첫번 째 오류 

(Database "/Users/*/* not found, either pre-create it or allow remote database creation (not recommended in secure environments) [90149-200] 90149/90149 (도움말)

 

처음에 h2를 설치했을때 웹에서 따로 찾아서 설치를 했었다. 

근데 이게 맥북의 버전 이슈? 로 권한 문제란다...shit..

 

그래서 이거는 다시 homebrew를 통해 설치했다. 

 

1. homebrew 에서 설치 

brew install h2

 

2. h2 서버 실행 

h2 -web

 

이렇게 서버를 실행하면

 http://172.30.1.21:8082 이런 url이 나오는데 이걸로 접속하면 h2 서버가 정상적으로 열렸다...

 

2. 두번 째 오류

Connection is broken: "java.net.ConnectException: Connection refused: localhost" [90067-232]

 

아.. 이거는 알아보니

첫번 째 문제를 해결하기 위해 처음 웹사이트에서 다운 후 brew를 통해 다시 설치 한 다음 

서버 실행할때 h2 -web 이렇게 실행해서 문제가 생긴거라고 한다. 

 

근데 좀 헷갈리는게 brew로 설치하고 바로 직후에 h2 -web 이렇게 서버를 실행했을 때는 문제가 생기지 않았는데 

tcp를 통해 접속하기 위해? 서는 다른 명령어를 사용해야 하는듯 싶다

 

h2 -tcp -web -pg

 

H2 서버 실행 명어 설명

1. h2 -web

 

  •  명령어는 H2 데이터베이스  콘솔을 실행한다. 웹 콘솔은 브라우저를 통해 데이터베이스에 접근할 수 있는 인터페이스를 제공한다. 그러나 이 명령어만으로는 TCP/IP 연결을 수신하지 않는다는 문제가 있다.

2. h2 -tcp 

  • 이 옵션은 H2 서버 TCP 드로 실행!  TCP 모드에서는 외부 클라이가 H2 데이터베이스에 연결할 수 있도록 TCP/IP 소켓을 통해 연결을 신한다. 이 모드가 활성화되어야 다른 플리이션이나 클라이트가 H2 데이터베이스에 연결할 수 있다 !
  • -pg : 이 옵션 PostgreSQL 호환 모드로 H2를 실행한다. 이 모드를 사용하면 H2 데이터베이스가 PostgreSQL의 SQL 문법과 기능을 지원하게 되며 이는 PostgreSQL과 성을 위해 유용하다

이렇듯 명령어 사용에 유의하자..! 알고 쓰자!!

 

 

1. sqld 준비 배경 

셤본지 몇개월이 흘렀지만... 작성해보기...헤..

 

저는 컴공 전공자로서 4학년 2학기때 2주 정도 공략해 시험을 봤습니다. sqld가 크게 개발자 취업을 할때 엄청 메리트 있는 요소는 아니지만 그래도 개발자로서 데이터베이스 기본을 다시 읽히고 자격증 취득을 목표로 준비를 했습니다. 

 

전공자 기준 2주 정도 준비를 했지만 제가 제시한 방법으로 하신다면 비전공자도 3~4주 정도면 괜찮은 준비 기간이 될 것 같습니다. 

저는 정처기도 보유를 하고 있고 전공 수업때 데이터베이스 관련 수업도 들었던 경험이 있어 수월한 감이 있었지만 그래도 시험 자체가 어려운 난이도의 시험은 아니기 때문에 충분히 가능한 시험이라고 생각합니다~

 

 

2. 시험 정보 

sqld는 데이터 자격 검정 사이트에서 접수가 가능하고 1년에 총 4회차로 이루어져 있고 시험 접수비는 5만원이었습니다.

저같은 경우는 지방에 살아서 시험 보는 장소가 근처에 없어서 기차타고 시험장이 있는 곳으로 가서 봤어요! 이런 것도 미리 알아봐서 시험장이 있다면 제 시간에 시험접수를 해 꼭 가까운 곳에서 볼 수 있도록 하면 좋을 거 같습니다!

 

시험은 총 2과목으로 1과목(데이터모델의 이해와 분석), 2과목(sql 이해 및 활용) 으로 이루어져 있습니다. 

1과목은 10문제이고 총 배점은 20점으로 문제당 각 2점!, 2과목은 40문제로 총 배점 80점으로 똑같이 문제당 2점입니당

시험시간은 90분 , 1시간 반정도 보았는데 저 같은 경우는 시험시간 꽉채워서 보고 나왔어요. 저는 항상 모든 시험 시간을 꽉채우는 타입이라.. ㅎㅎ

 

일단 제가 본 회차는 54회차로 76점으로 60점을 넘기며 합격을 했습니다. ㅎㅎ

 

3. 무조건 합격 공부 법 

3.1 이론 공부 

아무리 전공자라지만 그래도 이론 공부를 해야합니다. 왜나면 1과목 같은 경우는 다 암기이기 때문이죠..

이론서를 굳이 안사도 된다고 생각해요 !!! 돈아까우니까 ㅎㅎ 

 

저는 홍쌤 데이터 랩 유튜브 강의를 보면서 기본 이론은 다졌습니다. 생각보다 엄청 길지는 않아서 많이 시간날때마다 틈틈히 봤어요!

pdf로 자료를 공유해주시는데 이거를 따로 구해서 pdf에 요약을 하면서 일단 인강을 1회독을 했습니다. 

그후 시간이 없기 때문에 시간을 따로 내서 인강을 막 보지는 않았어요 대신에 밥먹는 시간, 이동하는 시간 등등 자투리 시간을 1회독 한 이후에 틈틈히 틀어놓아서 자연스럽게 개념을 익혔습니다 

 

 

제가 참고한 유튜브 홍쌤 링크입니다. 

https://youtu.be/rdfHFnqVoRw?si=1WpwoKdMZHM_stp2

 

 

3.2 개념 자료 

개념서를 따로 구비한 것이 아니기 때문에 홍쌤이 주신 자료도 좋았지만 불필요한? 내용도 있는거 같기도 했습니다. 물론 초반 개념 다지기 용으로는 좋았으나 조금 더 시험에 적합한 자료를 구했습니다! sqld 요약본 이렇게 검색하시면 시험용으로 너무 잘 정리해주셔서 블로그에 공유해 주신 분들을 많이 찾았어요. 그래서 그 자료를 프린터로 뽑아서 이것도 틈틈히 계속 읽었습니다. 

그리고 문제를 풀다보면 새로운 추가 개념, 이해안되는 것들은 같이 옆에 정리해서 보았어요!(저만의 노트를 만들기) 

 

제가 참고했을떄 너무 도움이 됐었던 pdf 를 공유해주신 블로그를 공유해드릴게욤

https://daebal.tistory.com/18

 

[ 합격자의 2024 SQLD 개념 정리 ] 2024 이후 개정된 SQLD의 개념정리 PDF 및 합격 후기

[ 개념정리 Notion link ]아무래도... Notion 정리본을 pdf로 컨버팅 한 것이기 때문에 Notion 링크에서 자료 확인하시는게 더 깔끔할겁니다 ㅎㅎ..[ 2024년 52회 SQLD 응시 및 합격자 ]SQLD 개정 후 첫 회차에

daebal.tistory.com

 

 

이렇게 제가 공부한 실제 자료들입니다..ㅎㅎㅎ

 

 

 

 

3.3 문제집 !!

여러분 ! sqld는 무조건 "노랑이" 입니다..! 

노랑이만 완벽하게 풀어도 시험 합격은 할 수 있어요 저는 한 기본 3회독 이상은 했고 모르는건 더 풀었던거 같아요 

저만의 표시방법을 만들어서 모르는건 세모, 중요한거 별표 등 이런식으로 풀때마다 표시를 했구요 

그리고 이게 문제집 자체로도 두꺼운 편은 아닌데 sqlp 과목과 합쳐진거라 실제 sqld 문제 수는 얼마 안돼요 

그래서 익숙해지면 하루만에 풀수도 ? ㅎㅎㅎ(이건 아닌강 ㅎㅎ)

 

아무튼 저는 1주일은 개념공부하는데 집중을 했고 나머지 1주일은 이 노랭이 책만 엄청 파서 공부를 했습니다. 

@@ 노랭이가 개정판이 있으니 꼭 개정판을 구매하시기 바랍니다.

 



 

 

 

문제를 잠깐 보면 알 수 있듯이 문제가 엄청 길어요

제 꿀팁은 문제를 절대 모두 해석하려고 하지 마세요 초반에 문제를 풀때는 선지를 모두 해석하는 게 중요한것은 맞지만

 

시험장에서는 시험시간 제한이 있으니 문제에서 중요하게 제시한 부분이 무엇인지, 문제를 잘 파악해서 쿼리에서 중요한 부분 쿼리에 집중을 하시는 것을 추천합니다. 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3.4 모르는 개념 및 문제는 ? 

문제를 풀거나 공부를 하실떄 아무래도 이해가 안되거나 질문하고 싶은 것들이 생길 수 있습니다. 

저는 네이버 데이터 '데이터 전문가 포럼 카페'를 이용해서 문제를 찾았어요 그러면 이미 다른 분들이 질문을 한 내용이 있거나, 아니면 제가 직접 질문도 할수 있습니다 !!

 그래서 강추 !!

https://cafe.naver.com/sqlpd

 

데이터 전문가 포럼 (빅데이터분석기사... : 네이버 카페

빅데이터분석기사, ADP, ADsP, SQLP, SQLD, DAP, DAsP, BIS 자격증 취득 등 데이터 전문가 커뮤니티입니다.

cafe.naver.com

 

 

3.5 자투리 꿀팁

이것만 집중해서 하는 것도 좋지만 저는 유튜브에 올라오는 sqld 인강, 문제풀이 자료들을 적극 활용했습니다. 

 

1. 이 강의는 주제별로 강의 챕터가 잘 나눠져 있어서 헷갈리는 부분 해결할때 참고했습니다. 

밥먹을때 틈틈히 봤던 기억이 납니다. 

 

https://www.youtube.com/watch?v=TN4syS7dyEk&list=PLDI0745yTBjXFuIFYqq3vzcQYuVyajFpC

 

 

2. 재미삼아 스피트 퀴즈도 했었는데 생각보다 초반에는 아무것도 모르겠었다는 점 ,, ㅋㅋㅋ

그래도 같이 공부할 떄 보면 좋았던거 같아요 

 

https://www.youtube.com/watch?v=rWdfFV8Wb18&t=80s

 

 

 

 

 

다들 활이팅!!! 한동안 바빠서 블로그 못쓴 나.. 다시 열심히 해야지 

오또케 ㅠ 나의 첫 이미지 ... ncp 활용일기.....감격스러워

 

1.  환경 및 개발 이유

현재 멀티캠퍼스 풀스택 부트캠프 과정에서 프로젝트를 진행하고 있다. 

백엔드는 springboot + mybatis , 프론트는 typescript + react 이다

 

- 기존에 이미지를 저장하는 로직은 백엔드의 정적폴더에 경로를 지정하고 -> 프론트에서 MultipartFile로 이미지 저장 및 수정을 요청하면 ->  service 단에서 지정한 정적폴더 경로(resources/static : 이게 자바에서 범용적인 정적 폴더일거야) 에 저장하고 디비에 이미지 폴더 이름을 저장하는 방식을 사용했다. 

- 이미지를 조회할때는 프론트에서 실제 백엔드 로컬서버에서 http://localhost:8001~~~~/이미지.Jpg 이런식으로 정적폴더에 접근해 이미지를 가져오게 했다 

 

- 배포를 위해서 이미지를 따로 저장하는 네이버클라우드플랫폼(ncp) Object Storage를 활용해 이미지를 저장하고 가져오는 방향을 추진했다. 

 

2. ncp 에서 기본 세팅 

멀티캠퍼스 측에서 이미 서브계정을 받았고 이 계정 생성같은 경우는 따로 설명하지 않겠다. 

 

1. 네이버 클라우드 콘솔에 접속해 Object Storage 에 접속해 버킷을 생성한다. 아래 링크대로 이용신청 후 버킷을 생성하면 된다. 

https://guide.ncloud-docs.com/docs/objectstorage-start 

 

2. api 인증키를 받아야하는데 우리같은 경우는 멀티캠퍼스에서 받은 서브계정이기 때문에 따로 메인계정에 api 인증키를 받을 수 있게 권한 요청을 하면 api 인증키를 받을 수 있다. 

 

3. 백엔드 설정 

3.1  build.gradle 설정 

네이버 클라우드 같은 경우는 aws s3 sdk 를 지원한다. 그래서 의존성에 이 한줄을 추가해주면 된다. 

implementation 'com.amazonaws:aws-java-sdk-s3:1.11.238'

 

3.2 application.properties

access-key와 secert-key는 api 인증키 받을 때 나온거다 그리고 endpoint는 나와 동일하게 쓰면 된다. 버킷 이름도 지정한걸로 쓰고, region도 설정한걸로 써라 

#ncp
ncp.objectstorage.access-key=ncp_iam_비밀이에요
ncp.objectstorage.secret-key=ncp_iam_비밀이에요
ncp.objectstorage.endpoint=https://kr.object.ncloudstorage.com
ncp.objectstorage.bucket-name=workspace(당신껄로해요)
ncp.objectstorage.region: kr-standard(당신껄로해요)

 

3.3 NcpStorage.config 

ncp object Storage에 연결하기 위한 설정으로 우리가 이미지를 저장하기 위해 필요한 AmazonS3Client를 빈 생성해 사용할 수 있도록 한다. 버킷이름은 이따 이미지 저장할때 쓰려고 반환했다. 

 
@Configuration
public class NcpStorageConfig {
@Value("${ncp.objectstorage.access-key}")
private String accessKey;

@Value("${ncp.objectstorage.secret-key}")
private String secretKey;

@Value("${ncp.objectstorage.endpoint}")
private String endpoint;

@Value("${ncp.objectstorage.bucket-name}")
private String bucketName;

@Value("${ncp.objectstorage.region}")
private String region;

@Bean
public AmazonS3Client objectStorageClient() {
return (AmazonS3Client) AmazonS3ClientBuilder.standard()
.withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endpoint, region))
.withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secretKey)))
.build();
}

public String getBucketName() {
return bucketName;
}
}

 

 

4. 코드 추가 

우리 프로젝트 같은 경우는 이미지를 저장하고 수정하는 기능들이 각 팀원별로 가지며 브랜치가 나눠져 있다. 그래서 모든 기능별로 서비스단에서 이미지를 저장로직을 추가하는게 비효율적이라고 생각했다. 그래서 따로 이미지 저장하는 함수와 삭제하는 함수를 가진 클래스를 만들어 

각 기능별로 클래스를 주입받아 함수를 사용하면 코드 한줄로 사용할 수 있다!!!1 (우린 너무 똑똑해 야무져 이뻐) 

 

4.1 FileService.java 

라는 이름으로 이미지 저장하고 삭제하는 클래스 만들어서 공통으로 사용하자 

 

@Service
@RequiredArgsConstructor
public class FileService {

private final AmazonS3Client amazonS3Client;
private final NcpStorageConfig ncpStorageConfig; // NCP 스토리지 설정 주입

public String putFileToBucket(MultipartFile file) {
if (file == null || file.isEmpty()) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Uploaded file is empty or null.");
}

String originalFilename = file.getOriginalFilename();
if (originalFilename == null) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Uploaded file has no original filename.");
}

String fileName = UUID.randomUUID().toString() + "_" + originalFilename.replace(" ", "_");
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(file.getSize());

try (InputStream inputStream = file.getInputStream()) {
// NCP 오브젝트 스토리지에 이미지 업로드
amazonS3Client.putObject(new PutObjectRequest(ncpStorageConfig.getBucketName(), fileName, inputStream, metadata));
return fileName; // 업로드된 파일 이름 반환
} catch (IOException e) {
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Image upload failed: " + e.getMessage());
}
}

public void deleteFileFromBucket(String fileName) {
try {
// NCP 오브젝트 스토리지에서 이미지 삭제
amazonS3Client.deleteObject(ncpStorageConfig.getBucketName(), fileName);
} catch (Exception e) {
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Image deletion failed: " + e.getMessage());
}
}
}

 

- putFileToBucket(MultipartFile file) : 이미지를 ncp oos 에 저장하는 함수 

  사용자들이 이미지를 저장할때 같은 이름으로 중복이 될 수 있다. 그래서 UUID를 활용해 이미지 이름앞에 특수값을 넣어주면 스토리지에 저장될때 이미지 이름이 겹칠 일이 없다. 

  metadata 객체를 사용하면 업로드할때 콘텐츠 유형, 길이 ,캐시 제어 등 정보를 설정 할수 있다. 그리고 InputStream을 활용해 이미지 아까 컨피그에서 의존성 주입 받은 amazonS3Client의 putObject함수를 사용하면 이미지가 저장된다. 

 

- deleteFileFromBucket(String fileName) : ncp oos에서 이미지를 삭제하는 함수 

   이거 같은 경우는 이미지를 수정할때 새로운 이미지가 들어오게 되는데 이때 기존 이미지를 삭제하고 새로운 이미지를 저장할때 그 삭제를 할 때 쓰는 친구다. 이거는 특별한거 없이 의존성 주입받은 amazonS3Client에 deleteObject()함수를 쓰면 끝난다. 

 

+ 아까 컨피그에서 버킷이름을 반환하게 했는데 저장하고 삭제할때 쓰기위해 반환한거임 >< 

 

 

자.. 이제 실제 코드에 적용해보자 

4.2 Controller 

이 컨트롤러는 유저와 관한 걸로 회원가입을 할때 쓰는 컨트롤러를 보여주겠다. 사실 여기는 기존에 정적폴더 경로로 저장했던 코드와 동일하다 그대로 MultipartFile로 파일 받고, ModelAttribute를 사용해 회원가입을 할때 body로 들어오는 데이터를 UserRequestDTO와 매칭해준다.  그냥 일반적인 회원가입 컨트롤러임 

근데 난 친절하고 나중에 까먹으니까 미래의 나를 위해 친절히 코드 넣어놈 ㅋ

@PostMapping("/user/register")
public ResponseEntity<String> registerUser(@ModelAttribute UserRequestDTO userRequestDTO,
@RequestParam(value = "memberImgFile", required = false) MultipartFile memberImgFile) {
return loginServiceImple.registerUser(userRequestDTO, memberImgFile); // 회원가입 처리
}

 

 

4.3 Service 

너무 좋다 혁신적이다. 위에서 만든 fileServie 의존성 주입해주고 , fileService.putFileToBucket(file)만 해주면 된다니 !! 나머지 코드들은 디비에 회원가입때 들어오는 정보들 저장하는거다 

@Autowired
private FileService fileService; // FileService 주입
public ResponseEntity<String> registerUser(UserRequestDTO userRequestDTO, MultipartFile memberImgFile) {

// 비밀번호 암호화
String encodedPassword = passwordEncoder.encode(userRequestDTO.getPassword());
userRequestDTO.setPassword(encodedPassword); // 암호화된 비밀번호로 설정

// 이미지 저장 로직 추가
if (memberImgFile != null && !memberImgFile.isEmpty()) {
String fileName = fileService.putFileToBucket(memberImgFile); // FileService를 사용하여 이미지 저장
userRequestDTO.setMemberImg(fileName); // DB에 저장할 파일 이름 설정
logger.info("Image uploaded successfully to NCP Object Storage: {}", fileName); // 성공 로그
} else {
userRequestDTO.setMemberImg(null); // 이미지가 없을 경우 null 설정
}

// DB에 저장하기 전 UserRequestDTO 상태 로그
logger.info("UserRequestDTO before saving to DB: {}", userRequestDTO);

try {
logger.info("Registering user: {}", userRequestDTO);
userMapper.registerUser(userRequestDTO);
UserResponseDTO user = userMapper.getUserByEmail(userRequestDTO.getEmail());
logger.info("회원가입 후 저장된 뱃지 저장용 유저의 아이디 : {}", user.getMemberId());
// 뱃지 생성 호출
badgeService.createBadge(user.getMemberId());
crewBadgeManager.createCrewBadge(user.getMemberId());
 
logger.info("성공로그 이메일 : {}", userRequestDTO.getEmail()); // 성공 로그
} catch (DataIntegrityViolationException e) {
logger.error("Data integrity violation: {}", e.getMessage(), e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("{\"Code\": \"DATA_INTEGRITY_VIOLATION\", \"Message\": \"데이터 무결성 위반.\"}");
} catch (Exception e) {
logger.error("Registration failed: {}", e.getMessage(), e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("{\"Code\": \"REGISTRATION_FAILED\", \"Message\": \"" + e.getMessage() + "\"}");
}

// 회원가입 성공 메시지를 JSON 형식으로 반환
return ResponseEntity.ok("{\"message\": \"회원가입 성공\"}");
}

 

- 이미지 수정하는거는 조금 더 여기서 추가되는게 있다. 

  1. 이미지 수정 요청이 들어옴 

  2. 해당 아이디로 기존에 저장했던 이미지 파일 이름을 디비에서 가져오는 mapper, xml 코드를 만든다. 

  3. 아까 FileService에서 만들었던 파일 삭제 함수로 기존 파일이름을 넣어서 삭제해주고 

  4. 저장하는 함수에 새로운 이미지 파일을 넣어서 보내주면 된다 !! 

 

 

포스트맨이든 프론트랑 연동해서 쓰면 정상적으로 

 

저장된게 보일거다 !!!!!!!!

 

 

 

 

 

5. 여기가 진짜 트러블 슈팅... 프론트에서 오브젝트 스토리지에 저장한 이미지 가져오기 

프론트에서는 특별히 고칠 건 없었다. 

프론트에서 백엔드의 정적폴더에 접근할때 기존에는 BaseURL(백엔드 URL)을 지정해놓고 디비에 이미지 파일 이름 조회하면 응답으로 내려오는 파일 이름을 붙여서 접근했다. 

 

예를 들어 이렇게 http://localhost:8001/static/aldifefslfjosdf.jpg 요딴식으로 

const BASE_URL = "https://localhost:8001";
<ProfileImage
src={
userInfo.memberImg === null
? "/img/default/UserDefault.png"
: `${BASE_URL}${userInfo.memberImg}`
}
alt="Profile" 
/>

 

이거를 이렇게 ncp에 맞는 url로 바꾸면 된다. 

https://<버킷 이름>.<엔드포인트>/<파일 이름> 형식이다. 그리고는 바꿀게 없다. 

 

 

 

 

근데 요청을 하니까 ... 이런 오류가 났다 ㅠㅠㅠㅠ

 

공식 문서를 통해 cors문제인지 막 찾아봐도 안보임 ㅠㅠ

https://guide.ncloud-docs.com/docs/objectstorage-troubleshoot-common

 

 

 

6. 이미지 내려받기 해결 

근데 oos에 저장된 이미지들을 보던 중에 올라간 이미지를 클릭하고 꼼꼼히 살펴보던 중 권한관리 탭에서 전체공개에서 공개안함이 되어 있었다. 분명 우리는 처음에 버킷 생성하고 뭐시기.. 앞에 초반 작업 문서보고 따라했을 때 분명 public으로 했다. 

 

근데 알고보니까 이미지를 올리고 올려진 이미지에 대해서 접근하는 권한은 따로 설정을 해줘야 한단다...쉣더뻑킹임 이런건 처음 설정할때 나중에 퍼블릭으로 해줘야 한다고 대문짝만하게 광고해야한다. 하루동안 삽질 했다 

 

해결법 

1. ncp 콘솔에서 저장된 이미지에 대해 직접 다 퍼블릭읽기 권한 주기 -> 이런 귀찮고 ㅁㅊ짓은 하지말자 

2. aws cli 사용해 파일 권한 변경 멍령어를 써서 읽기 권한 주기 -> 이거 aws cli 설치해야한다. 나는 가난한 용량의 대학생 개발자이기에 뭐 설치하는거 끔찍히 싫어한다. 

3. s3 호환 api 사용해 설정 -> 이거는 그냥  어려워보였다 이해하기 싫었어요. 헤헤 

 

.

.

.

마지막 해결법은 이미지 업로드 할때 putObject 함수에서 퍼블릭 읽기 권한을 추가!!!

하면 된단다... 처음부터 알았으면 이렇게 코드 짰을거다. 그니까 이거는 이미지 저장하는 코드에서 권한을 줘서 처음 저장할때부터 퍼블릭 권한을 가진 이미지들이 생성되는거다. 그러면 따로 뭔가를 하지 않아도 자동으로 퍼블릭 상태의 이미지들을 프론트에서 받을 수 있었다. 

아까 위에서 코드의 재활용성을 높이기 위해서 만든 이미지 저장 , 삭제 클래스 FileService만 조금 수정해주면 된다. 


@Service
@RequiredArgsConstructor
public class FileService {

private final AmazonS3Client amazonS3Client;
private final NcpStorageConfig ncpStorageConfig; // NCP 스토리지 설정 주입

public String putFileToBucket(MultipartFile file) {
if (file == null || file.isEmpty()) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Uploaded file is empty or null.");
}

String originalFilename = file.getOriginalFilename();
if (originalFilename == null) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Uploaded file has no original filename.");
}

String fileName = UUID.randomUUID().toString() + "_" + originalFilename.replace(" ", "_");
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(file.getSize());

try (InputStream inputStream = file.getInputStream()) {
// NCP 오브젝트 스토리지에 이미지 업로드 시 퍼블릭 읽기 권한 추가
PutObjectRequest putObjectRequest = new PutObjectRequest(
ncpStorageConfig.getBucketName(),
fileName,
inputStream,
metadata
).withCannedAcl(CannedAccessControlList.PublicRead); // 퍼블릭 읽기 권한 설정

amazonS3Client.putObject(putObjectRequest);

return fileName; // 업로드된 파일 이름 반환
} catch (IOException e) {
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Image upload failed: " + e.getMessage());
}
}

public void deleteFileFromBucket(String fileName) {
try {
// NCP 오브젝트 스토리지에서 이미지 삭제
amazonS3Client.deleteObject(ncpStorageConfig.getBucketName(), fileName);
} catch (Exception e) {
throw new ResponseStatusException(HttpStatus.INTERNAL_SERVER_ERROR, "Image deletion failed: " + e.getMessage());
}
}
}

 

 

하.. 만족해....잘거야.. 내일은 백ㅇ네드 프론트 둘다 배포할거야 ncp 재미지다 헤헤헤헤ㅔ 졸려핑 

 

문제 상황 

현재 spring boot를 사용하고 있고, 공공데이터포털에서 open api 를 사용해 연결하는 작업을 하던 중이었다.. 

분명히 키는 잘 발급 받았는데 자꾸 아래와 같이 에러가 떴다....

 

에러를 넘겼지만 당시 상태 코드는 200으로 넘어왔다... 그래서 나에게 리턴하는 메시지는 서비스키 문제라고 하지만 서비스키 문제가 아닐것이라고 짐작 . 

 

 

 

 

공공데이터 포털에서 open api 를 가져오기 위한 초기 세팅 

1. 일단 내가 원하는 데이터를 선택하고 활용신청을 하면 된다. 

2. 이때 서비스 키를 바로 사용하면 정상적으로 ? 요청이 안될 수 도 있다고 했다. 그래서 무려 난 개발 3일 전에 신청을 해놨다 ㅋㅋ

3. 서비스키(encoding key)와 callbackurl(end point), datatype(api가 내려 줄 데이터 타입)등을 application.properties에 아주 잘 적용했다. 

4. 처음 오류가 났을때 작성했던 코드 

package com.example.mini.please_mini_pjt.hosapi.ctrl;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.ResponseEntity;

import java.net.URI;
import java.net.URISyntaxException;

@RestController
@RequestMapping("/api")
public class HosApiController {

    @Value("${openApi.serviceKey}")
    private String serviceKey;
    
    @Value("${openApi.callBackUrl}")
    private String callBackUrl;

    @Value("${openApi.dataType}")
    private String dataType;

    @GetMapping("/Hosinfo")
    public ResponseEntity<String> getMethodName(@RequestParam(value = "Q0") String Q0, 
                                                @RequestParam(value = "Q1") String Q1,
                                                @RequestParam(value = "QT") String QT) {
        System.out.println("client end point : /api/Hosinfo");
        System.out.println("serviceKey = " + serviceKey);
        System.out.println("callBackUrl = " + callBackUrl);
        System.out.println("dataType = " + dataType);
        System.out.println("params = " + Q0 + "\t" + Q1 + "\t" + QT);

        // 요청 URL 생성
        String requestURL = callBackUrl + 
                            "?serviceKey=" + serviceKey + 
                            "&Q0=" + Q0 + "&Q1=" + Q1 +
                            "&QT=" + QT;

        System.out.println("url check = " + requestURL);

        // RestTemplate을 이용하여 GET 요청
        RestTemplate restTemplate = new RestTemplate();
        try {
            // URI 클래스를 사용하여 URL 인코딩
            URI uri = new URI(requestURL);

            // API 요청을 보내고 응답 받기
            String jsonString = restTemplate.getForObject(uri, String.class);
            System.out.println("API response = " + jsonString);

            // 요청 결과를 그대로 반환
            return ResponseEntity.ok(jsonString);
        } catch (URISyntaxException e) {
            // URI 생성 중 오류 발생 시 처리
            System.out.println("URI Syntax Error: " + e.getMessage());
            return ResponseEntity.status(400).body("잘못된 요청 URL입니다.");
        } catch (Exception e) {
            // 요청이 실패했을 경우 오류 메시지 출력
            System.out.println("API 요청 중 오류 발생: " + e.getMessage());
            return ResponseEntity.status(500).body("API 요청 중 오류 발생");
        }
    }
}

 

 

 

해결 과정

1.  오류 메시지처럼 서비스 키가 문제인지 아닌지 아는 방법 !!

코드를 자세히 보면 requestUrl 을 만들고 이를 확인하기 위해

출력하는 부분이 보일 것이다.

 

System.out.println("url check = " + requestURL);

이때 출력되는 url을 웹에서 테스트 해보면 !

아주 잘 데이터가 넘어온다.. ㅋㅋ

그렇다는 건 서비스키가 문제가 아니라는 뜻 ...

나의 못생긴 코드가 문제라는 뜻이다..

 

 

 

 

 

 

2. URI 클래스 사용하기 

 삽질해보니 다른 분들은 이 방법대로 해서 해결이 된걸 보고,,,, 수정했는데
하지만 나는 해결이 안됐다. 그래도 참고한 자료를 넣을게요 아래 블로그 보고 했습니다. 

 

https://velog.io/@cco2416/%EC%A1%B8%EC%97%85%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EA%B3%B5%EA%B3%B5%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%8F%AC%ED%84%B8-service-key-is-not-registered-error-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95

 

[졸업프로젝트]공공데이터 포털 service key is not registered error 해결 방법

공공데이터 포털의 API를 졸업프로젝트를 진행하면서 사용하게 되었는데, 이 과정에서 "service key is not registered error"를 만나게 되었다. 이 오류를 해결하기 위한 과정이 적혀있다.

velog.io

 

3. 마지막 해결법 !! 인코딩 문제..

1. Service Key를 다시 인코딩하지 말기:

서비스 키는 이미 인코딩된 값이므로, 이를 다시 인코딩하면 문제가 발생할 수 있다. 현재 serviceKey에 인코딩된 값이 들어가 있다면, URLEncoder.encode()로 중복 인코딩하지 않도록 해야 한다...

2. 한글 파라미터는 명시적으로 인코딩하기:

한글로 되어 있는 Q0, Q1 파라미터는 브라우저에서 자동 인코딩되지만, 스프링에서 직접 요청을 만들 때는 URLEncoder로 인코딩을 해줘야 한다. 

 

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.GetMapping;

import com.example.mini.please_mini_pjt.hosapi.domain.HosDetailDTO;
import com.example.mini.please_mini_pjt.hosapi.domain.HosItemDTO;
import com.example.mini.please_mini_pjt.hosapi.service.HosApiService;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

@RestController
@RequestMapping("/api")
public class HosApiController {
    @Autowired
    private HosApiService hosApiService;


    @Value("${openApi.serviceKey}")
    private String serviceKey;
    
    @Value("${openApi.callBackUrl}")
    private String callBackUrl;
    
    @Value("${openApi.dataType}")
    private String dataType;

    @Value("${openApi.callBackUrl2}")
    private String callBackUrl2;

    @GetMapping("/Hosinfo")
    public ResponseEntity<List<HosItemDTO>> getMethodName(@RequestParam(value = "Q0", required = false) String Q0,
                                                @RequestParam(value = "Q1", required = false) String Q1,
                                                @RequestParam(value = "QT", required = false) String QT) {
        System.out.println("client end point : /api/Hosinfo");
        System.out.println("serviceKey = " + serviceKey);
        System.out.println("callBackUrl = " + callBackUrl);
        System.out.println("params = " + Q0 + "\t" + Q1 + "\t" + QT);

        HttpURLConnection http = null;
        InputStream stream = null;
        String result = null; 
        List<HosItemDTO> list = null;

        try {
            // 한글 파라미터 인코딩 처리
            String encodedQ0 = URLEncoder.encode(Q0, StandardCharsets.UTF_8.toString());
            String encodedQ1 = URLEncoder.encode(Q1, StandardCharsets.UTF_8.toString());
            String encodedQT = URLEncoder.encode(QT, StandardCharsets.UTF_8.toString());

            // 이미 인코딩된 serviceKey를 다시 인코딩하지 않음
            String requestURL = callBackUrl +
                                "?serviceKey=" + serviceKey +
                                "&Q0=" + encodedQ0 +
                                "&Q1=" + encodedQ1 +
                                "&QT=" + encodedQT;

            System.out.println("url check = " + requestURL);

            

            //수정본 
            URL url = new URL(requestURL);
            http = (HttpURLConnection)url.openConnection();
            System.out.println("http connection = " + http);
            int code = http.getResponseCode();
            System.out.println("http response code = " + code);
            if(code == 200) {
                stream = http.getInputStream();
                result = readString(stream);
                System.out.println("result = " + result);
                list = hosApiService.parseXml(result);
                
            }


        } catch (Exception e) {
            e.printStackTrace();
        } finally {

        }
        return new ResponseEntity<>(list, HttpStatus.OK);
       
    }
    
    

    public String readString(InputStream stream) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(stream,"UTF-8"));
        String input = null ;
        StringBuilder result = new StringBuilder();
        while((input = br.readLine()) != null) {
            result.append(input + "\n\r");
        }
        br.close();
        return result.toString();
    }
}

 

우웩우에구우게욱웩 

안녕하세욤 ㅎㅎ 정처기 필기편을 얼마전에 작성하고 반응이 좋아서 ㅠㅠ 실기도 열심히 육수 뽑아서 작성해볼게요!!

필기를 안보신 분들은 필기편을 먼저 보고 오는 것도 좋은 방법입니당 

https://dev-leeyjstar.tistory.com/entry/%EC%A0%95%EB%B3%B4%EC%B2%98%EB%A6%AC%EA%B8%B0%EC%82%AC-%EB%8F%99%EC%9D%BC-%ED%9A%8C%EC%B0%A8-%ED%95%A9%EA%B2%A92024%EB%85%84-1%ED%9A%8C%EC%B0%A8-%ED%95%84%EA%B8%B0%ED%8E%B8-%EB%AC%B8%EC%A0%9C%EC%A7%91-%EA%B3%B5%EB%B6%80%EB%B2%95

 

정보처리기사 동일 회차 합격(2024년 1회차) - 필기편 / 문제집, 공부법

정보처리기사 2024년 1회차를 동일 회차 합격한 후기를 써봅니다.....합격발표가 나온지는 몇달 됐지만 너무 바빠서 이제야 후기를 작성...합니다...  일단 저의 스펙은 전공자..! 이지만 아직 대

dev-leeyjstar.tistory.com

 

 

 

저 같은 경우는 컴퓨터공학과 전공자로서 3학년 이수 끝나자마자 바로 1회차 시험을 도전했구요 당시 시험 준비했을 떄 딱 평범한 전공자 3학년 수준에서 도전했다고 생각해주시면 됩니다. 

(아무래도 전공자이다보니 탈락하면 매우 부끄러울 거 같아 무조건 동일회차가 목표였습니다. 그래서 전공자가 아니라고 생각하면서 꼼꼼하게 장기적으로 공부했습니다. 이 글이 비전공자, 고득점 목표자에게도 효과적이기 바랍니다. ^^ ! )

 

1. 정보처리기사 실기 소개 

일단 필기를 합격해야 실기를 볼수 있겠죠오.. 필기시험일 기준으로 약 2달하고 1주일 정도 뒤에 실기 일정이 있었습니다. 실기 같은 경우는 날짜가 하루밖에 없어서 무조건 큐넷 접수할때 빠르게 하는게 중요해요 (대학교 수강신청정도 까지는 아니지만 그래도 제 시간에 넣어야 좋은 위치에 시험장에서 볼 수 있습니다. ㅠ) 두달이라고 생각하시고 준비를 하셔야 됩니다. 

실기 같은 경우는 필기랑 다르게 코딩관련된 문제들이 주이기 때문에 무조건 프로그래밍 언어를 공부하셔야 합격할 수 있어요 

 

 

실기 합격률을 보시다 시피 쉬운 합격률은 아니에요 제 주변에 저와 함께 시험 준비를 했던 전공자 동기들만 봐도 알고 있는거니까 가볍게 준비를 했다가 떨어지시는 분들도 많았어요 

그러니 꼭 꼼꼼히 준비하셔야 합니다. 

 

 

 

 

2. 시험 후기 

 

저는 동일회차 100만점에 84점으로 합격을 했구요! 실기는 60점만 넘기면 합격을 받을 수 있습니다.

 

제가 이렇게 고득점을 얻을 수 있었던 건...

 

제 생각에는 필기때 얼마나 이론을 많이 쌓았냐가 좀 중요한거 같아요.

저는 솔직히 프로그래밍언어 말고 다른 암기형 문제들은 거의 다 맞았거든요 그 이유가 이론을 제대로 다회독 했기 때문이에요 프로그래밍언어는 기본 베이스나, 전공자처럼? 그럼 코딩 센스도 좀 필요하고 많이 풀어봐야 하는데 나머지는 열심히 다회독 하면 많이 맞을 수 있어요. 

 

 

 

+ 제 기억으로는 아스키코드 꼭 알아야 풀 수 있는 문제도 있었어요. 저 같은 경우는 문제 풀이 방식은 다 맞았는데 이 코드 값을 잘못 넣어서 틀렸던 문제...ㅎㅎ 이런거 처럼 기본적인 전공지식이 있으면 좋을 거 같아요

 

 

그렇지만 필기때 많이 준비를 못하거나, 지식이 부족해도 충분히 2달 동안 빡세게 한다면 가능합니다. ㅎㅎ 아자아자(저도 했잖아요!)) 

 

 

참고로 실기 준비는 2달동안 최소 4시간 이상, 주말에는 6시간 이상은 하려고 했어요 ( 집중 잘되면 8시간은 공부했다는,,,ㅋㅋ)

 

 

 

 

 

 

3. 인강 추천 

사실 필기때는 인강을 안봤었는데 실기때는 필기처럼 찍을 수가 없잖아요 무조건 이해를 하고 넘어가야 문제를 풀 수 있어요. 그래서 아무리 잘 알더라도 자만하지 않고 인강을 1회독을 목표했습니다. 

사실 저 같은 경우는 학교 졸작이랑 병행하면서 시간이 많이 부족했어요. 그래서 저한테 필요한 부분, 헷갈린 부분만 인강을 봤어요. 

예를 들어 진짜 중요한 화이트박스, 블랙박스, 디자인패턴 같은 건 종류도 많고 암기하기도 이해하기도 어렵거든요 

이렇게 중요한것들 위주로 인강을 봤습니다. 아무래도 기본 베이스가 부족하거나 시간이 넉넉하신 분들은 그래도 처음부터 끝까지 다 보셔도 좋을 것 같아요 (저는 개인적으로 부족한 부분들이 다 이해가 되서 너무 좋았습니다. ) 

 

 

 

 

인강은 수제비 실기 패키지로 구매를 했구요 필요한 부분만 보느라 30퍼밖에 진도율이 안되네요 ㅎㅎ

음 저는 전공자라 프로그래밍언어에 기본 지식이 있어서 사실 따로 공부하지는 않았어요 시간도 부족했기도 했고 

근데 비전공자분들은 유튜브에 정처기 자바 / c/ 파이썬 이렇게 무료로 된 목록별로 무료 동영상들 많으니까 전체 이론 공부 들어가기 전에 가볍게 꼭 듣기 바랄게요 

주변에서 공부하면서 부족하면 사람들이 프로그래밍언어 인강은 따로 다 들었다고 하더라고요

(저는 개인적으로 흥달쌤 강의 추천합니다. 인강은 여기서 듣고 문제 풀거나 어려운 부분들은 흥달쌤 유튜브 동영상으로 다 해결했어요. 예를 들어 흥달쌤 서브넷 문제 풀이 이렇게 검색했습니다. ) 

 

 

 

 

 

4. 교재 추천 

저는 필기때와 마찬가지로 수제비 실기 책을 구매했어요. 실기책이랑 위에 수제비 실기 인강이랑 세트라고 보시면 됩니다. 

그리고 제일 중요한게 수제비 실기 책  + 수제비 파이널 문제집 을 꼭 구매하시길 추천드려요!! 

(제가 책을 같이 찍어서 올릴려고 했는데 다음 회차 준비하는 동기에게 책을 넘겨주는 바람에 책 사진은 못찍었습니다..헤헤)

 

 

1. 일단 실기 책을 위주로 최소 3회독은 했었구요 아무래도 필기때 이미 다회독 해놓은 상태라 실기때는 3회독 정도 했던거 같아요

 

2. 그리고 실기떄는 실제로 용어를 많이 알고 있어야 해요. 그래야 찍신이 없더라고 문제를 풀 수 있으니까요! 

그래서 꼭 암기해야하는 것들은 무조건 두음이랑 같이

요점정리로 만들어서 암기했습니다 

-> 저는 이거 없으면 떨어졌을 거에요 ㅋㅋ

 

3. 요점정리의 기준 

무조건 2회독 이상은 하면 어떤 부분이 중요한지, 암기해야하는지 알 수 있어요 그런 중요한 부분들 위주로 정리를 해주세요 (저는 최대한 많이 하려고 했어요)

 

특히 보안, 네트워크 이런 단원에서는 다 암기니까 꼼꼼히 정리해두시길..! 

 

그냥 본인이 헷갈리면 정리해요!

 

 

 

 

 

 

 

 

여기서 두음이란..

수제비 책에서 쉽게 암기할 수있도록 두음법칙을 사용해 정리해주신거에요 

이것만 있으면 무조건 합격가능입니다.. 

저 같은 경우는 이렇게 두음 pdf를 다운받아서 그 옆에 페이지쪽수 , 영어는 스펠링 풀어서 적어놓거나, 관련된 이론들도 같이 정리해서 두음 외울 때마다 같이 볼 수 있도록 했어요. 

근데 이게 두음이 좀 많거든요 처음에는 외우기 힘들 수 있는데 중요한 거 위주로 먼저 꼭 외우시고 나머지는 선택적으로 외우시면 될거 같아요 무조건 다 암기해야지 이런 강박은 없으셔도 됩니다. 

 

 

 

 

 

 

 

위에서 이론서 3회독, 요점정리 및 두음 암기가 조금 이루어졌다면 파이널 모의고사를 풀면 됩니다. 

혹시 몰라 링크를 밑에 달아두겠습니다. 광고 이런거 없습니다. 저는 쪼고미 블로거라.. ㅋㅋ

이게 기출문제 + 수제비에서 만든 모의고사 문제들로만 이루어져 있는데요 이게 문제풀이 양이 많고 모의고사는 생각보다 많이 어려워요 

그래도 이거 풀 수 있는 정도면 무조건 합격이에요 ㅋㅋ 

이게 양이 많아서 다 못 풀수 있어요 저는 시험 2주 전에 풀었거든요 2주전까지는 미친듯이 이론서 다회독, 이론서에 있는 틀린 문제들 반복해서 풀고 2주부터는 이것만 계속 풀고 이해 안되면 다시 이론서 찾아보는 식으로 했습니다. 

 

여기서 책안에서 기출문제는 4회독 했고 모의고사는 1회독 정도 했어요 모의고사는 어렵고 띠용한 문제들도 있어서 다 풀지는 않았지만 3/2 이상은 풀고 틀린 문제만 한번 더 봤어요 

 

https://product.kyobobook.co.kr/detail/S000212570871

 

2024 수제비 정보처리기사 실기 FINAL 실전 모의고사 | 윤영빈 - 교보문고

2024 수제비 정보처리기사 실기 FINAL 실전 모의고사 | 〈본서의 특징〉 ㆍ NCS 반영!! 기출문제 완벽 분석, 실전 모의고사 수록 ㆍ 집필진과 10만 명 회원이 함께하는 커뮤니티! ㆍ 수험생들에 의해

product.kyobobook.co.kr

 

 

그리고 마지막으로 수제비 카페를 많이 이용했어요 모르는 문제들은 카페에 올리면 친절이 답해줍니다. 그리고 시험 몇일 전에? 수제비 카페에 실기 현재 나올만한 문제? 들로 선생님들께서 실기 보기전 미리 테스트 할수 있게 시험지를 올려주세요 (예상문제 모의고사? 같은거) 

이거를 시험 전날에 풀었는데 이거는 조금 어려웠어요 이때 모의고사 볼떄 커트 간당간당해서 떨어질 수도 있겠다 싶었는데 일부로 난이도를 높게 내주시는것 같더라구요 

그래서 저거 파이널 어느정도 풀고 실제 실기 보기 전날에 카페에 올라오는 예상 시험지까지 풀어보시길 꼭 추천합니다. 

 

수제비 카페 링크 

https://cafe.naver.com/soojebi

 

수제비- IT 커뮤니티 (정보처리기사... : 네이버 카페

수제비-수험생 입장에서 제대로 쓴 비법서(정보처리기사, 정보처리산업기사, 빅데이터 분석기사, ADsP 등)

cafe.naver.com

 

 

공부법 최종 정리 

1. 유튜브에서 정치기 java/c/python 정리된 영상 보기 (프로그래밍 언어 지식이 부족할 경우) 

2. 실기 이론서 1회독하기 ( 그냥 읽어보면서 1회독해요) 

3. 수제비 인강을 겸행해서 2회독

4. 요점정리하거나 / 두음pdf 보면서 또 3회독

(회독할때 이론서 사이에 있는 문제들은 최소 3회독하기 + 여기서 틀린문제 위주로 다시 풀어도 됩니다. 맞은 문제는 다시 풀 시간이 없으니 헷갈리거나 틀린거 표시해서 꼭 다시 푸세요 많이 도움됩니다. )

5. 어느정도 최소 3회독이 됐다면 파이널 모의고사 풀기 (기출문제는 무조건 4회독 이상하고 나머지 모의고사도 시간남으면 최대한 풀어보기) 

6. 위에 1~5번을 할동안 어려운거는 수제비 카페 적극활용, 시험 전에 카페에 올라오는 예상 문제 풀어보기

 

 

 

5. 꿀팁 

 

 

필기때도 했던 이야기인데 사실 제일 중요한건 다회독이에요 모든 시험합격, 제가 학점도 관리를 잘 했었는데요.

꿀팁은 그냥 짜투리 시간을 잘 썻냐 안쎳냐 차이인거 같아요. 밥먹을때, 학교 쉬는 시간, 이동시간, 잠자기전, 샤워할떄, 화장실 갈때 핸드폰 들고 다닐 수 있을 때는 무조건 헷갈리는 부분 사진 찍어서 다시 보고 그랬어요 ( 예를 들어 오늘 학교 등교시간에 암호 알고리즘 중 대칭키 종류들을 꼭 외우자) 이렇게 목표를 설정해서 외우기도 했죠 (그냥 미친놈이에요 저는 왤케 열심히 했지 ㅋㅋ)

 

이렇게 암기할거 문제집을 사진찍어서 폴더에 저장하거나

요점정리한것들 캡쳐해놓거나, 두음 pdf 핸드폰에 저장해서 계속 봤어요 

 

그리고 유튜브에 있는 자료들도 적극 활용하세요. 

제가 기본 베이스는 수제비 책, 인강으로 틀을 잡았지만 시간날때는 아무거나라도 유튜브에 있는 자료들 그냥 검색해서 봤어요 

예를 들어 그냥 유튜브에 정처기 실기 데이터베이스 검색해서 시나공껏도 자기전에 보고 자고 샤워하면서도 틀면서 샤워했다는 ㅋㅋ

 

아무튼 그렇게 짜투리 잘 활용하면 충분히 할 수 있습니다. 

개인적으로 서브넷, ip 이런 어려운 문제들은 흥달쌤을 애용했어요 (예를 들어 2024년 1회차 정처기 실기 흥달쌤 5번 문제 이렇게 검색하거나, 회차별로 문제풀이 해주신 영상들 보면서 어떻게 어려운 문제들 푸는지 감을 익혔습니다. ) 

 

 

 

 

그리고 출제 비중 위주로 단원별 앞에 꼭 체크해서 많이 나오는걸 많이 보세요....! 저는 상중하로 체크해서 단원별 앞에 체크해놓고 중요한건 다회독, 요점정리를 다했어요 (불필요한건 하지마세요....!) 그리고 이해 안가면 넘어가요... 넘어가서 시간 지나면 또 이해되고 그러니 한 곳에서 오래 머물지 마세요..!

 

 

 

필기때도 자료를 첨부했긴 했지만 필기 글을 안볼 사람들을 위해 출제기준, 비율 자료를 넣었습니다..

 

다들 꼭 합격하세요(댓글로 질문 편하게 주셔도 됩니당 ! 다들 화이팅!! )

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

정보처리기사 출제기준(2023.1.1.~2025.12.31).hwp
0.08MB

정보처리기사 2024년 1회차를 동일 회차 합격한 후기를 써봅니다.....

합격발표가 나온지는 몇달 됐지만 너무 바빠서 이제야 후기를 작성...합니다...

 

 

일단 저의 스펙은 전공자..! 이지만 

아직 대학교에 재학중이고 3학년 끝나고 바로 4학년이 되는 해에 바로 접수를 해서 봤기 때문에 사실 전공자지만 3학년 학부생 수준이고, 학생으로서 부족한게 많습니다. ! 

 

그럼에도 학부때 다루는 내용(데이터베이스, erd, 자바, c , 파이썬,,,) 이런 부분에서는 익숙한게 훨씬 많아 도움이 된건 사실입니다. 

전공자로서 시험에서 떨어지면 너무 자존심이 상할거 같더라구요.. 그래서 비전공자처럼 열심히 공부했습니다. 하나하나 꼼꼼히 꾸준히 했습니다. ㅎ하하

그래서 제 점수가 고득점을 노리시는 분, 비전공자들도 충분히 도움이 되실 ...? 거라고 생각합니다...(그러길 바랍니다^^) 

 

 

정보처리기사 시험 소개 

1. 과목 구성 및  합격 기준 

정보처리기사는 일단 총 5과목으로 구성되어있숩니다. 

1. 소프트웨어설계 2. 소프트웨어개발 3. 데이터베이스구축 4. 프로그래밍언어활용 5. 정보시스템구축관리

 

객관식으로 4지선다형, 문제은행식이기 때문에 충분히 기출문제집만 돌려도 합격을 할 수 있습니다. 

합격 기준은 100점을 만점으로 하여 과목당 40점 이상, 전과목 평균 60점 이상을 맞으면 되기 때문에 생각보다 도전해볼 만한 점수네요 ㅎㅎ

 

 

 

최근 5개년 시험 합격률만 봐도 필기 같은 경우는 충분히 쉽게 합격할수 있을겁니다. 

 

 

 

2. 시험 후기 

필기같은 경우는 사실 기출문제만 돌려도 충분히 합격할 수 있습니다. 하지만 우리의 목표는 실기까지 원큐에 합격하는거잖아요?

그러기 위해서는 필기때 흐름을 잘 잡아놓는게 중요해요!!!!!( 필기때 이론을 최소한 잡아야 실기를 합격할 수 있는거 같아요 )

제 주위의 저와 함께 본 전공자 동기들도 필기는 바로 합격했는데 실기는 떨어진 경우도 많았습니다. 전공자에게도 실기는 쉽지않아요 

그렇기 때문에 필기부터 이론을 꼭 다회독!하시길 ...

 

필기 점수

 

일단 제 필기 점수는 무려 100,,점이 나와버린 사람입니다..

솔직히 저는 이론서를 무려 4회독을 했습니다. ㅋㅋ

 

준비기간은 약 2달정도 잡았습니다. 

사실 필기 준비 기간을 넉넉히 잡은 이유는 실기 때문이었어요

실기준비 기간이 개강하고 졸작을 준비해야 하는 시기여서 필기때는 아무래도 이론을 다 잡아야 실기 준비가 수훨할 거 같아서  방학기간이라  하루에 4시간은 공부했던거 같습니다. (물론 공부 안한날도 많긴한데 그래도 최대한 하려고 했어요) 

 

 

 

 

 

 

 

3. 문제집 추천 / 인강 - 수제비 

ㅇㄹ

저는 솔직히 인강은 안봤구요 

이 이론서만 가지고 4회독을 했습니다. 수제비 이론서가 생각보다 너무 자세하고 쉽게 설명되어 있습니다. 

그리고 수제비카페가 잘 커뮤니티화되어 있어서 모르는 문제나 질문이 생기면 카페에 질문도 할 수 있어요 

실기때는 인강을 봤었는데 이거는 실기편에서 작성하겠습니당

 

 

그리고 두음 법칙 !!

수제비의 제일 큰 장점이 중요하게 암기할 부분을 두음으로 정리해놨다는거에요 두음법칙이라는게 뭐냐면 ㅎㅎㅎ"동경결상 유분페원비오" 뭐이런거... 아주 시험볼떄 도움이 됩니다. ㅜ

 

개꿀팁 !!!

수제비카페에서 두음법칙을 싹 다 모아놓은 pdf 파일을 올려놓는데 저 같은 경우는 그 pdf 를 다운받아서 두음법칙 옆에 해당하는 이론서의 페이지 쪽수를 적어놨어요. 이게 왜 좋냐면 문제를 풀다보면 두음법칙은 생각나는데 이 개념이 뭔지 헷갈리는 경우가 많아요 그럼 두음법칙만 보는게 아니라 쪽수를 적어놓은 이론서를 같이 바로 찾아보면서 헷갈리는 부분을 다시 잡는거에요 

 

 

 

수제비 카페 링크

https://cafe.naver.com/soojebi

 

 

수제비- IT 커뮤니티 (정보처리기사... : 네이버 카페

수제비-수험생 입장에서 제대로 쓴 비법서(정보처리기사, 정보처리산업기사, 빅데이터 분석기사, ADsP 등)

cafe.naver.com

 

 

 

 

과목별 출제 비중

 

 

 

사실 수제비가 좋았던게 이론뿐만아니라 단원별로 해당 문제들이 같이 부록되어 있는데 문제들이 생가보다 괜찮은 문제들이 많았던거 같아요  그래서 저 같은 경우는 이 문제들도 최소 세번 풀었고 문제집에 직접 문제를 푸는게 아니라 위에 틀린거만 표시해서 나중에 또 풀고 또 풀고 이렇게 표시해둔거 위주로 풀었어요

 

이렇게 이론서 회독이 끝나면 기출문제집을 풀어주면 되요 

사실 기출 문제집은 시험 2주 정도 남기고 풀었던거 같아요 급하게 서점가서 기출문제집 사느라 대충 인기있던거 골랐었는데 시나공 기출을 풀었어요 생각보다 풀기 편하게 잘 되어 있어서 시나공도 괜찮았던 거 같아요 

 

그리고 정처기가 5과목에 범위가 생각보다 정말 광범위해요 넓게 공부를 해야하는데 이때 시험이 어떤 과목에서 비중이 크게 나오는지도 알고 있어야 해요 그래야 회독할 때 비중이 낮은 과목은 후순위로 두고 비중이 높은 과목을

더 많이 볼수 있기 때문이죠 

 

 

 

 

 

 

출제기준도 참고하면 좋을 것 같아요

정보처리기사 출제기준(2023.1.1.~2025.12.31).hwp
0.08MB

 

 

 

결론 

1. 수제비 이론서 다회독( 최소 3번이상은 하기) - 1회독만 어렵지 그 이후로는 쌉가능

2. 두음법칙 중요한거 위주로 다 외우고 외울 수 있는거 최대한 외우기

3. 기출문제집 최소 3개년 3회독 

 

 

 

3. 합격 꿀팁 

사실 1회독이 어렵지..1회독 진짜 엄청 오래 걸리거든요? 거즘 2주 넘게 했던거 같은데 그 후로 다회독은 2일만에 2회독, 3회독 할수 있습니다..!

그리고 저 같은 경우는 자기 전, 밥먹으면서, 화장실 ,, ㅎ하하 이런 짬이 날때 유튜브에서 돌아다니는 정처기 요약 강의 같은거를 봤어요 아무거나 상관없어요 진짜 아무거나 상관없고 최신버전으로 해서 봤어요 이게 은근 도움되는게 생각지도 못한 부분들, 수제비에는 표시가 안됐지만 다른 곳에서는 설명하는 부분들, 내가 헷갈렸던 부분들 이런것들 그냥 유튜브 본다고 생각하고 편하게 틀어놓고 밥먹고 샤워하고 화장하고 그랬어요 ... ㅎㅎ

 

 

 

 

 

그리고 휴대폰에 저는 외워야 하는 이론들을 공부하다가 아 잘 안외워진다, 헷갈린다, 이거중요하다 하는 것들은 그냥 핸드폰에 사진을 찍고 폴더에 넣어서 길다닐때, 공강일때, 틈날때마다 봤어요 

 

직장인들이나 일하시는 분들 시간 진짜 부족할거에요 저도 다른거랑 병행하면서 해서 무조건 짬나는 시간을 중요하게 생각해서 공부했어요 

짬날때 암기를 하면 시간 절약을 할 수 있습니다. 

 

 

실기를 위해서라도 필기때 기본을 잡아두어요 !!

화이팅 할수 있습니다. 

why?

그 동안 딥러닝을 실행했을땐 주피터 노트북이나 특히 코랩 gpu를 활용해 머신러닝 공부를 했었다.

하지만 캡스톤의 이유 + 딥러닝 공부를 더 해보기로 결심을 했기때문에 vscode 기반의 환경 구축을 해보려고 한다. 

캡스톤의 주제가 (웹 + ai)의 융합이기에 vscode를 활용하는 것이 편할 것이라고 생각했다.


1. 첫번째 목표 :  vscode에서 아나콘다 가상환경 만들기 

왜 가상환경을 구축해야할까? 

여러 프로젝트를 수행하면서 프로젝트마다 필요한 라이버러리와 여러 환경들이 요구하는 것이 서로 상이할 수 있다.

만약 서로 가상환경없이 프로그램이 같이 존재한다고 하면 서로 의존성 문제나 업데이트 할 경우 일어나는 충돌 , 버전문제 등 여러 문제들이 생길 수 있다. 

그래서 가상환경을 구축해야함 ! 쉽게 설명해 여러 구성원이 집에서 거주할때 단독주택에서 사냐 vs 원룸 형태에서 사냐의 차이이다. 단독주택에서는 공동으로 용품을 사용해야하지만 원룸에서는 구성원에 따라 자유롭게 용품을 사용할 수 있다. 

 

setp1. 아나콘다 설치 

https://www.anaconda.com/download#windows

 

Free Download | Anaconda

Anaconda's open-source Distribution is the easiest way to perform Python/R data science and machine learning on a single machine.

www.anaconda.com

난 이미 설치 되어있어서 건너뜀요

 

 

setp2. vscode에서 파이썬 설치하기

vscode가 없다면 설치하세요우

이것도 건너뜀요

 

 

step 3. conda 가상환경 만들기

1.  버전확인 : 설치한 콘다와 파이썬이 잘 설치되었는지 터미널에서 확인합니두

 

- 파이썬 버전 확인 

python --version

 

- 콘다 버전 확인 

conda --version

 

- 현재  환경 리스트 (콘다 환경리스트)

conda info --envs

 

 

2. 현재 파이썬 버전에 맞는 가상환경 생성하기 (파이썬 버전을 지정하지 않을 경우에는 최신버전으로 설치됨요)

my_env라는 가상환경을 만들고 환경리스트 확인을 통해 확인해볼게욤

conda create -n my_env python=3.11.5

 

 

 

step 4. vscode에서 새로 만든 가상환경 적용해보기

command +shift + p 입력 -> select interpreter 입력 -> 위에서 만들었던 'my_env' 환경이 보임 ! 이걸 선택하면 끝! 

 

 

step 5. 가상환경 제거하기 

방금 만든 따끈따끈한 'my_env' 환경을 삭제해볼게요  명령어 실행후 다시 가상환경리스트를 보면 삭제되고 기존에 것만 있는것을 확인할 수 있습니다!

conda env remove -n my_env

 


2. 두번째 목표 : m1, m2 칩에서 gpu 가속화 하기 ( pythorch) (mps) 

대부분 머신러닝 개발을 한다면 cpu보다 gpu가 필수가 된다. gpu는 수천개 코어로 병렬 데이터 처리에 매우 효율적이고 대량 계산 작업을 동시에 수행할 수 있어 머신러닝 모델의 훈련과 추론 단계에서 cpu보다 훨씬 빠르고 복잡한 계산을 하면서도 에너지 효율이 좋다.

또한 ai 개발을 위해 사용되는 다양한 프레임워크와 라이브러리가 cpu 지원을 제공함으로서 개발자가 높은 성능의 ai 솔루션을 쉽게 구현할 수 있다. 

 

대부분 머신러닝 코드는 Nvidia 그래픽 카드를 사용하는 cuda로 작성하는데 mac os 지원을 중단함에 따라 복잡해졌다.

하지만 pythorch 에서 새로운 릴리즈를 함으로서 m1, m2칩에서 gpu 사용이 가능해졌다. 

 

* 환경요구사항 : macOS 12.3 이상, Python 3.7 이상, 그리고 PyTorch 1.12 이상이 필요합니다.

 

 

(step 0. 앞에서 구축했던 가상환경을 구축해놓고 실행을 해도 좋다. )

 

step 1. pythorch 설치하기 

pip3 install --pre torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/nightly/cpu

 

 

step 2. vscode에서 m1, m2 프로세서 인식이 되고, mps가 현재 환경에서 지원되는지 확인하기

아래와 같이 확인이 된다면 성공

 

디바이스를 'mps' 설정하는 것이 포인트

import torch

print(f"mps 사용 가능 여부: {torch.backends.mps.is_available()}")
print(f"mps 지원 환경 여부: {torch.backends.mps.is_built()}")

if torch.backends.mps.is_available():
    mps_device = torch.device("mps")
    x = torch.ones(1, device=mps_device)
    print (x)
else:
    print ("MPS device not found.")

 

 

step 3. 학습테스트 

프로세스 인식을 했으니 실제 학습에 사용이 가능한지 확인해야한다. 

 

1.  코드가 돌아가는 중에 맥북이 '활성상태보기' 기능 에서 gpu가 활용되는 것이 급격히 증가한다면 성공

2. cpu 학습 과 gpu 학습 시간 비교하기  ( 와우 무려 cpu는 4.4 s , gpu는 0.2s 차이가 나네욤 ㅎㅎ)

 

import torch
import time

# CPU에서의 연산 시간 측정
start_cpu = time.time()
tensor_cpu = torch.randn(10000, 10000)
result_cpu = tensor_cpu @ tensor_cpu
end_cpu = time.time()
print(f"CPU에서의 연산 시간: {end_cpu - start_cpu}초")

# MPS(GPU)에서의 연산 시간 측정
if torch.backends.mps.is_available():
    start_mps = time.time()
    tensor_mps = torch.randn(10000, 10000, device="mps")
    result_mps = tensor_mps @ tensor_mps
    end_mps = time.time()
    print(f"MPS(GPU)에서의 연산 시간: {end_mps - start_mps}초")
else:
    print("MPS(GPU) 사용 가능한 환경이 아닙니다.")

 

 

끝... 휴 이제 더 열심히 공부해야지..

1. api 란 ? 

일단 api의 개념부터.. 

Application Programming Interface 한 프로그램에서 다른 프로그램으로 데이터를 주고 받기 위한 방법

ex) 메뉴판 : 손님↔가게 유저와 서버가 주고 받기 위한 방법

  • api가 가져와할 내용
  1. 요청방식이 들어가야 한다(method) (get 요청) ex) 데이터를 요청할지 , 보내달라고 할지
  2. 무슨 자료 요청할지 (enapoint) ex) 어떤 데이터를 요청할 것인가 웹툰? 댓글? 뉴스?
  3. 파라미터 / 자료요청에 필요한 추가 정보 ex) 내 아이디, 이름 , 웹툰 몇 화
  • public / private / partner API  :   public API (누구나 사용가능한 공인 API) , private API (사내에서 몰래 API) , partner API (미리 정해둔 유저만 쓰는 API)
  • 모든 프로그램은 API 를 가질 수 있다운영체제 : windows api ( 윈도우가 제공하는 기능 사용가능) , datavase 관리 프로그램 api (DB와 관련된 기능들 사용가능)

 

2.1 RestFul API 란? 

서버와 클라이언트과 통신을 하기 위한 규약(Rest) → (이 것을 rest하게 api를 설계하면 효율적으로 개발을 할 수 있다)

- Re REpresentational : 표현  

- s State : 상태  

- t Transter : 전송

해석 : "자원의 표현을 가지고 상태전달한다." 

 

REST의 정의 : 분산 시스템 설계를 위한 아키텍쳐 (=구성) 스타일 / 네트워크 아키텍쳐 원리 모음/ 제약 조건의 원리 / 사이트 구성 원리

Rest : “사이트 구성 원리 “  ,    Restful : “Rest한” ,     Restful API : “Rest 한 API”

해석:  사이트 구성 원리를 준수하는 API

 

예시 1. GET youtube.com/feed/subscriptions 여기서 자원은 - 구독한 유튜버들의 영상들 이고 , 상태는 - get

 

2.2 왜 Restful API 를 사용해야 할까?

GET /

GET /sport/soccer 스포츠 안에서 축구라는 종목을 요청한다.

DELETE /sport/soccer/players/11 스포츠라는 것 안에서 축구라는 종목을 하는 플레이어들중 11번을 삭제하라

->  위 처럼 rest api 메시지를 읽는 것만으로도 메시지가 의도하는 바를 명확하게 파악

->  기본적으로 HTTP 프로토콜을 사용해서 서버와 클라이언트가 요청하고 응답을 처리한다. 

-> HTTP 인프라를 그대로 사용하기 때문에, REST API 사용을 위한 별도의 인프라 구축이 필요없다. 그래서 우리는 restful api 사용

 

결론 

Restful API 에서는 클라이언트는 단순히 리소스를 요청하면 서버는 해당 리소스를 응답해주기만 하면 된다.

ex) GET /sport/soccer/player → 서버 입장에서는 player라는 정보를 전달해주기만 하면 된다.

—> 결론 : 클라이언트와 서버가 독립적으로 운영이 가능! restful api를 사용해야 하는 이유!

 

2.3 구현 방법 (rest는 자원의 표현을 가지고 상태를 전달한다. )

자원(Resource) : URI에 명시 - /feed/subscriptions

표현(Representational) : Header로 전달 - text/html, image/gif , text/* (여기서 *은 text의 모든 타입을 일컫는다)

상태(State) : HTTP Method - GET, POST, PUT, DELETE

→ subscription은 클라이언트가 전달하는 데이터가 아니라 subscription에 메소드를 띄웠을 때 클라이언트가 전달받고자 하는 데이터를 헤더로 명시한다. 이것을 rest에서 ‘표현’이라고 얘기한다.

 

 

- 자원 (Resouce) : 모든 URI는 자원으로 나타낸다.

GET /sports/soccer/show

GET /sports/soccer/players/11/delete

→ 축구라는 것을 보여줌/ 플레이어 11번을 삭제함 —> 하지만 rest 설계 목적과는 다름

GET /sports/soccer

DELETE /sports/soccer/players/11

→ 더 명확하기 위해선 리소스를 자원으로 나타내야 한다! : URI에는 동사가 들어가선 안됌 무조건 자원(명사)가 들어가야 한다.

 

 

- 상태(State) : 모든 동작은 메소드로 나타낸다(상태=동사)

GET /sports/soccer → soccer를 보여주라

DELETE /sports/soccer/players/11 → 11을 지워주라

  • PUT (수정) /waters/:삼다수 (어떻게 수정할지는 body를 통해 보냄)
  • POST (생성) /waters
  • DELETE (삭제) /waters/:삼다수
  • GET (조회) /waters

- 표현 (Representational) : 리소스의 응답 타입은 Header로 나타낸다.

GET /chaanel/best_vis → 클라이언트 “JPG 확장자의 프로필 사진만 응답해주세요” (같은 메소드에 같은 경로인데 사진만 받고싶음)

Content-Type: text/html; charset=utf-8 //내가 전달하는 데이터가 html이라는 텍스트며 chareset은 utf-8이다.

→ 클라이언트가 전달하는 데이터의 타입 “요청하는 데이터의 타입” : 헤더로 받고 싶은 응답 타입을 명시해 줄 수 있다.

 

Accept : image/jpg

Accept: text/html, image/png //여러개 명시 가능

→ 클라이언트가 “응답받고 싶어 하는 데이터의 타입” : Accept 라는 헤더로 명시할 수 있다.

-> 어떤 응답을 받을지 모를 때 브라우저가 자동으로 설정해서 보내는 Accept를 사용하면 됨

 

Restful API 설계 원칙

  1. Uniform Interface (일관된 인터페이스)
  2. stateless (무상태성)
  3.  cacheable(캐시 가능) 
  4. code on demand
  5. layered system(계층형 시스템)
  6. client/serer

→ 이미 나머지는 원칙이 적용되어 있어 인터페이스만 rest하게 설계하면 된다.

2.4 Http 메소드 9가지 

  • GET : uri 형식으로 웹 서버 측 리소스(데이터)를 요청 , 이때 요청 받은 uri의 정보를 검색해 응답한다.
  • HEAD: 메세지 헤더(내부 문서 정보) 취득
  • GET방식과 유사, 응답에 바디가 없고 응답코드와 HEAD만 응답한다, 웹서버 정보 확인, 버전확인, 최종 수정일 등 조회시 사용
  • POST : 내용 전송( 파일 전송 가능), 요청된 자원을 생성(create)한다.
  • PUT : 내용 갱신 위주 (파일 전송 가능)
  • 요청된 자원을 수정(update)한다, 모든 데이터를 수정할 때 사용한다. EX) 삼다수와 관련된 모든 데이터를 바꾸고 싶을 때
  • PATCH : PUT 과 유사, 자원(데이터)의 일부를 교체하기 위해 사용한다. EX) 삼다수의 일부(예를 들어 이름)만 바꾸고 싶을 때
  • DELETE : 요청된 자원을 삭제(delete)한다.
  • CONNECT :요청된 자원에 대해 양방향 연결을 시작한다는 의미, 주로 웹 서버에 프록시 기능을 요청할 때 사용한다.
  • OPTION : 목표 리소스와의 통신 옵션을 설명하기 위해 사용, 시스템에서 지원되는 메소드 종류 확인할 수 있다.
  • TRACE : 클라이언트로부터 Request Packet의 변조 가능성이 있는데, 이때 서버에 도달한 최종 packet의 request packet볼 수 있다,
  • 요청을 보낸 곳에 어떤 요청이 가공되어 있는 지 등을 조사할 수 있다.

1. 개념

Asynchronous JavaScript and XML의 약자로, 자바스크립트의 라이브러리 중 하나다.

- XMLHttpRequest객체를 사용해 빠르게 동작하는 동적인 웹 페이지를 만들기 위한 개발 기법

- 웹 페이지 전체를 로딩(새로고침)안해도 웹 페이지 일부분 갱신 가능(로드된 후 데이터 요청, 보내기 가능)

-> 자바스크립트를 사용한 비동기 통신이며, 클라이언트와 서버간에 XML 데이터를 주고 받는 기술

더보기

비동기 방식은 웹 페이지를 로드하지 않고 데이터를 불러온다.

Ajax를 통해 서버에 요청을 해도, 멈춰있지 않고 해당 프로그램은 계속 돌아가며 시간도 빠르다. 화면을 리로드할 경우 전체 리소스를 다 가져올 필요없이 일부분만 가져오기에 장점이 있다

- 백그라운드 영역에서 서버와 통신해 그 결과를 웹페이지 일부분에만 적용

- JSON, XML, HTML, 텍스트 파일 등 의 형태로 데이터 주고 받는다 

- 구성요소 : html, css, DOM, JSON, XML, XMLHTTPRequest, js

2. 한계 

- 클라이언트 풀링 방식(클라이언트가 서버에 데이터를 요청하는)으로, 서버 푸시 방식의 실시간 서비스는 no

- 바이너리 데이터 no, Ajax 스크립트가 포함딘 서버가 아니느 다른 서버로 요청 no

- 클라이언트의 pc로 Ajax 요청을 보낼 수 no

- Ajax 는 동적 페이지 렌더링을 하기 때문에 자바스크립를 해석하니 못하는 검색엔진에서는 내용이 검색되지 않다는 문제점이 존재

- 자바스크립트를 반드시 써야 한다. 모든 웹브라우저에서 공통으로 지원되는 프로그래밍 언어는 아직까지는 자바스크립트 하나 뿐이다. 따라서 꺼버리면 Ajax 기반 사이트는 화면의 일부만 그려진다. 

 

3. 동작원리 

① : 사용자에 의한 요청 이벤트가 발생합니다.

② : 요청 이벤트가 발생하면 이벤트 핸들러에 의해 자바스크립트가 호출됩니다.

③ : 자바스크립트는 XMLHttpRequest 객체를 사용하여 서버로 요청을 보냅니다.

    이때 웹 브라우저는 요청을 보내고 나서, 서버의 응답을 기다릴 필요 없이 다른 작업을 처리할 수 있습니다.

④ : 서버는 전달받은 XMLHttpRequest 객체를 가지고 Ajax 요청을 처리합니다

⑤와 ⑥ : 서버는 처리한 결과를 HTML, XML 또는 JSON 형태의 데이터로 웹 브라우저에 전달합니다.

  이때 전달되는 응답은 새로운 페이지를 전부 보내는 것이 아니라 필요한 데이터만을 전달합니다.

⑦ : 서버로부터 전달받은 데이터를 가지고 웹 페이지의 일부분만을 갱신하는 자바스크립트를 호출합니다.

⑧ : 결과적으로 웹 페이지의 일부분만이 다시 로딩되어 표시됩니다.

 

- Ajax를 이용한 웹응용 프로그램은 js코드를 통해 웹서버와 통신을 한다. 이는 사용자의 동작에는 영향을 주지 않으면서도 백그라운데에서 지속해서 서버와 통신할 수 있다. 

- 일반적인 http 프로토콜 -> 단방향 통신  : 클라이언트에서 요청을 보내고 서버쪽에서 응답을 받으면 연결이 끊어진다. 화면의 내용을 개싱하기 위해 다시 요청을 보내고 응답을 받으며 페이지 전체를 갱신 (엄청난 자원낭비)

- Ajax : Http 페이지 전체가 아닌 일부만 갱신 가능하도록 XMLHttpRequest 객체를 통해서 서버에 요청 -> Json이나 XML형태로 필요한 데이터만 받아 갱신하기 때문에 그만큼의 자원과 시간을 아낄 수 있다. 

 

4. 예제

4-1. XMLHttpRequest를 사용한 예제

<html>
 <head>
  <script type="text/javascript">
   var request = new XMLHttpRequest(); // XMLHttpRequest 생성
   request.open("GET", "//namu.wiki/raw/틀:틀%20모음/"); // 데이터를 GET Method로 요청
   request.send(); // 실제 Send
   request.onreadystatechange = function() {
    if ( request.readyState == 4 && request.status == 200 ) { // request가 끝났으며(4), 성공적(200)인 경우. request.onload=()=>{} 으로 교체해도 가능하다.
     document.getElementById("content").innerHTML = request.responseText; // #content 태그 내의 내용을 받아온 텍스트로 교체.
    }
   };
  </script>
 </head>
 <body>
  <div id="content"></div>
 </body>
</html>

4-2. Fetch API 사용 예제 

<html>
 <head>
  <script type="text/javascript">
   fetch("//namu.wiki/raw/틀:틀%20모음/") // fetch API로 데이터를 요청
    .then((response) => {
     if (response.ok) { // HTTP Status가 성공적인 (200 등) 경우
      return response.text(); // Response Body를 text로 꺼내옴
     } else { // 4xx/5xx 에러로 요청 실패
      return Promise.reject(`Error code ${response.status}`);
     }
    }).then((text) => {
     document.getElementById("content").innerHTML = text;  // #content 태그 내의 내용을 받아온 텍스트로 교체.
    }).catch(() => { // 네트워크 문제일 경우만 reject됨
     console.warn('network problem');
    });
  </script>
 </head>
 <body>
  <div id="content"></div>
 </body>
</html>

4-3. jQuery를 이용한 예제 

<html>
 <head>
  <script type="text/javascript">
   $.ajax({
    url: "//namu.wiki/raw/틀:틀%20모음/",
    method: "GET",
    dataType: "text",
    success: function(data) {
     $("#content").html(data);
    }
   })
  </script>
 </head>
 <body>
  <div id="content"></div>
 </body>
</html>

-> $.ajax 함수를 이용해서 자체적인 AJAX를 지원해주기 때문에, 콜백함수만 넣어주면 간단히 해결된다. 

 

MVC에서 모델은 애플리케이션의 정보(데이터)를 나타내며, 뷰는 텍스트, 체크박스 항목 등과 같은 사용자 인터페이스 요소를 나타내고, 컨트롤러는 데이터와 비즈니스 로직 사이의 상호동작을 관리한다.
  • 는 사용자가 볼 결과물을 생성하기 위해 모델로부터 정보를 얻어 온다.
  • 뷰는 화면단, 사용자 인터페이스와 같이 보여지는 화면 부분을 의미한다. 

1. 뷰 분리 전 

const express = require('express');
const app = express()

app.get("/", (req, res) => {
res.send(`
<!DOCTYPE html>
<html lang="ko">
 
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
 
<body>
여기는 루트입니다.
</body>
 
</html>`)
});

app.get("/login", (req, res) => {
res.send(`
<!DOCTYPE html>
<html lang="ko">
 
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
 
<body>
<input type="text" placeholder="아이디"><br>
<input type="text" placehodler="비밀번호"><br>
<button>로그인</button>
</body>
 
</html>`)

})

app.listen(3000, function () {
console.log("서버 가동 ");
})

 

2. 뷰 분리 후 

1. 뷰 폴더를 따로 분리해준다. 

폴더 views > 폴더 home > 파일 index.ejs, login.ejs 생성 

 -> 이때 ejs는 안에 html코드를 어떤 엔진으로 해석할지 정하는 것 

 

2. index.ejs 파일에는 루트 경로의 코드를 옮기고 , login.ejs 파일에는 로그인 경로의 코드를 옮긴다. 

 

3. 앱세팅  : 화면 뷰를 위한 뷰엔진 세팅하기 

const express = require('express');
const app = express()

//앱세팅
app.set("views", "./views");
app.set("view engine", "ejs");


app.get("/", (req, res) => {
res.render("home/index");
});

app.get("/login", (req, res) => {
res.render("home/login");
})

app.listen(3000, function () {
console.log("서버 가동 ");
})

render 함수를 사용해 도메인에 들어왔을 때 ejs 코드들로 이동할 수 있게 연결해준다. 

'Bakend > Node.js' 카테고리의 다른 글

npm 백엔드 1탄  (0) 2023.09.01

+ Recent posts